【NOI2015模拟8.19】图(SPFA)
2018-02-03 08:43
323 查看
Description
给定一个 n 个点 m 条边的无向图,进行多次询问,每次询问点 a 是否能经过恰好 c 条边到达点 b(当然,可以对于一条边可以来回经过多次) 。
Input
第一行三个数 n,m,q,其中 q 表示询问数。
接下来 q 行,每行三个数 a,b,c。
Output
对于每次询问,如果存在一种走法,输出 TAK,否则输出 NIE
Sample Input
8 7 4
1 2
2 3
3 4
5 6
6 7
7 8
8 5
2 3 1
1 4 1
5 5 8
1 8 10
Sample Output
TAK
NIE
TAK
NIE
Data Constraint
对于 50%的数据,n<=800。
对于 100%的数据,2<=n<=5000,1<=m<=5000,1<=q<=1000000,1<=a,
b<=n,1<=c<=10^9。
所以我们只需求出每一个点到达目的的最短路,就是N次SPFA。
处理一下边的奇偶性就好了。
为什么要处理奇偶性?因为假设你要走c步,而c是个奇数,那你最优的路径是偶数边,那么显然不符合题意,无解啊
那么我们就要多开两个数组,一个存走奇数边的最短路,一个存走偶数边的最短路。
假设要走2m+1步,你最短路要2n步,那么你就少走2(m-n)+1步了
注意到这里有个1,我们就开两个最短路数组计算好了。
于是就可以切了。
Code
给定一个 n 个点 m 条边的无向图,进行多次询问,每次询问点 a 是否能经过恰好 c 条边到达点 b(当然,可以对于一条边可以来回经过多次) 。
Input
第一行三个数 n,m,q,其中 q 表示询问数。
接下来 q 行,每行三个数 a,b,c。
Output
对于每次询问,如果存在一种走法,输出 TAK,否则输出 NIE
Sample Input
8 7 4
1 2
2 3
3 4
5 6
6 7
7 8
8 5
2 3 1
1 4 1
5 5 8
1 8 10
Sample Output
TAK
NIE
TAK
NIE
Data Constraint
对于 50%的数据,n<=800。
对于 100%的数据,2<=n<=5000,1<=m<=5000,1<=q<=1000000,1<=a,
b<=n,1<=c<=10^9。
The Solution
解法很显然,对于每一个询问是否存在一种走法,我们只需比较一下这个从A点走c步到达B点的c步是否大于从A点到B点的最短路径嘛。证明显然。所以我们只需求出每一个点到达目的的最短路,就是N次SPFA。
处理一下边的奇偶性就好了。
为什么要处理奇偶性?因为假设你要走c步,而c是个奇数,那你最优的路径是偶数边,那么显然不符合题意,无解啊
那么我们就要多开两个数组,一个存走奇数边的最短路,一个存走偶数边的最短路。
假设要走2m+1步,你最短路要2n步,那么你就少走2(m-n)+1步了
注意到这里有个1,我们就开两个最短路数组计算好了。
于是就可以切了。
注意
还有一点,就是还是手打队列吧,我就是用了STL的queue导致T了80我也很无奈~~Code
#include <cstdio> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> #include <queue> #define fo(i,a,b) for (int i=a;i<=b;i++) #define fd(i,a,b) for (int i=a;i>=b;i--) #define N 5005 #define INF 1 << 30 using namespace std; struct Edge { int to,next; Edge(void){} Edge(int a,int b) : to(a),next(b){} }E[N * 2]; struct node { int Odd,Eve; }Dis ; //queue <int> Q; int Final ,tot = 0,n,m,q,d[N * 5]; bool Flag ; int read(int &n) { char ch = ' '; int q = 0, w = 1; for (;(ch != '-') && ((ch < '0') || (ch> '9'));ch = getchar()); if (ch == '-') w = -1,ch = getchar(); for (; ch >= '0' && ch <= '9';ch = getchar()) q = q * 10 + ch - 48; n = q * w; return n; } void Link(int x,int y) { E[++ tot] = Edge(y,Final[x]),Final[x] = tot; E[++ tot] = Edge(x,Final[y]),Final[y] = tot; } void Spfa(int x,int id) { memset(Flag,false,sizeof(Flag)); //Q.push(x); Flag[x] = true; fo(i,1,n) Dis[id][i].Odd = Dis[id][i].Eve = INF; Dis[id][x].Eve = 0; int l = 0,r = 1; d[1] = x; //while (! Q.empty()) while (l < r) { int now = d[++ l]; //int now = Q.front(); //Q.pop(); Flag[now] = false; for (int k = Final[now];k;k = E[k].next) { if (Dis[id][now].Odd + 1 < Dis[id][E[k].to].Eve) { Dis[id][E[k].to].Eve = Dis[id][now].Odd + 1; if (! Flag[E[k].to]) { Flag[E[k].to] = true; //Q.push(E[k].to); d[++ r] = E[k].to; } } if (Dis[id][now].Eve + 1 < Dis[id][E[k].to].Odd) { Dis[id][E[k].to].Odd = Dis[id][now].Eve + 1; if (! Flag[E[k].to]) { Flag[E[k].to] = true; //Q.push(E[k].to); d[++ r] = E[k].to; } } } } } int main() { freopen("xor4.in","r",stdin); freopen("data.out","w",stdout); read(n),read(m),read(q); fo(i,1,m) { int x,y; read(x),read(y); Link(x,y); } fo(i,1,n) Spfa(i,i); while (q --) { int x,y,z; read(x),read(y),read(z); if (x == y && Final[x] == 0) {printf("NIE\n");continue;} if (z & 1) { if (z >= Dis[x][y].Odd) printf("TAK\n"); else printf("NIE\n"); } else { if (z >= Dis[x][y].Eve) printf("TAK\n"); else printf("NIE\n"); } } return 0; }
相关文章推荐
- JZOJ3786. 【NOI2015模拟8.19】图
- JZOJ 3786. 【NOI2015模拟8.19】图
- 【jzoj3771】【NOI2015模拟8.15】【小 Z 的烦恼】
- JZOJ3789. 【NOI2015模拟8.20】编辑器
- JZOJ 3789. 【NOI2015模拟8.20】编辑器
- 【省选专题一】图论 jzoj 3936. 【GDOI2015模拟11.22】假期计划 spfa
- JZOJ3975. 【NOI2015模拟1.17】串
- 【NOI2015模拟1.10】B组黑白树
- 【NOI 2015模拟】总结
- 【NOI2015模拟9.9】取石子(博弈)
- 【JZOJ3973】【NOI2015模拟1.10】【NOI2013湖南省队集训】黑白树(wbtree)(并查集)
- 【JZOJ3819】【NOI2015模拟9.9】【hdu 4111】取石子(博弈+贪心+记忆化搜索)
- 【NOI2015模拟YDC】游戏
- jzoj3819 [NOI2015模拟9.9]取石子
- Jzoj3769【NOI2015模拟8.14】A+B
- 【省选专题一】图论 jzoj 3821. 【NOI2015模拟9.9】文理分科 最小割
- JZOJ 3769. 【NOI2015模拟8.14】A+B
- JZOJ.3777【NOI2015模拟8.17】最短路(shortest)
- NOI2015模拟SXK 字符串游戏 后缀数组预处理+主席树查询
- 【NOI2015模拟8.20】编辑器