您的位置:首页 > 其它

POJ 3259 Wormholes (寻找负权回路)

2016-11-05 15:41 155 查看
题目大意:有n个点m条双向路,w条单向路,输入的数据中前两个表示两点之间有路,前m条路表示这条路所花费的时间,后w条单向路表示可以回到过去某个时间,现在问你从某个点走之后是否会看到自己还没出发时的样子。

如果有负权回路,即一个回路中点的权值总和为负数,那么就能看到没有出发时的自己,因为自己回到了出发之前的时间。

用SPFA算法进行解,不断的松弛边,如果存在负权回路那么每一次松弛都会使距离更小,所以会无限松弛,所以判断一下一个点的入队次数,次数大于n时说明有负权回路。

AC代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define INF 0x3ffffff
using namespace std;
const int maxn=30000;
int first[maxn],sign;
struct node
{
int to,w,next;
}edge[maxn*2];
void creat()
{
for(int i=0;i<=maxn;i++)
first[i]=0;
sign=1;
}
void add_edge(int u,int v,int w)
{
edge[sign].w=w;
edge[sign].to=v;
edge[sign].next=first[u];
first[u]=sign++;
}
int SPFA(int n)
{
int dis[maxn],vis[maxn],outque[maxn],q[maxn],i=1,iq=1;
for(int i=0;i<=maxn;i++)
{
dis[i]=INF;
vis[i]=0;
outque[i]=0;
}
dis[i]=0;
q[iq++]=1;
vis[i]=1;
while(i!=iq)
{
int top=q[i];
vis[top]=0;
outque[top]++;
if(outque[top]>n)
return 1;
for(int k=first[top];k;k=edge[k].next)
{
int TO=edge[k].to;
if(dis[TO]>dis[top]+edge[k].w)
{
dis[TO]=dis[top]+edge[k].w;
if(!vis[TO])
{
q[iq++]=TO;
vis[TO]=1;
}
}
}
i++;
}
return 0;
}
int main()
{
int t,n,m,W;
int u,v,w;
scanf("%d",&t);
while(t--)
{
creat();
scanf("%d %d %d",&n,&m,&W);
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
}
for(int i=0;i<W;i++)
{
scanf("%d %d %d",&u,&v,&w);
add_edge(u,v,-w);
}
int num=SPFA(n);
if(num==1)
puts("YES");
else
puts("NO");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: