您的位置:首页 > 其它

【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。

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spfa