POJ 3259
题目大意:
就是判断给出的图中是否存在一个负权环,如果有的话,那么这个人转了一圈之后时间总和小于零,代穿越到之前了,也就满足了他。。。
大致思路:
裸的spfa判负权环,如果有一个点入队的次数大于总结点数,那么就代表存在一个负环。
代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
#define inf 9999999
int n,m,w,s,e,t;
struct Node
{
int to;
int cost;
Node(int too,int costt)
{
to=too;
cost=costt;
}
};
vector<Node>V[2505];
int vis[505];
int cnt[505];
int dis[505];
int spfa()
{
for(int i=0; i<=505; i++)
{
vis[i]=0;
cnt[i]=0;
dis[i]=inf;
}
queue<int>Q;
Q.push(1);
cnt[1]++;
vis[1]=1;
dis[1]=0;
while(!Q.empty())
{
int top=Q.front();
Q.pop();
vis[top]=0;
for(int i=0; i<V[top].size(); i++)
{
if(dis[V[top][i].to]>dis[top]+V[top][i].cost)
{
dis[V[top][i].to]=dis[top]+V[top][i].cost;
if(!vis[V[top][i].to])
{
Q.push(V[top][i].to);
vis[V[top][i].to]=1;
cnt[V[top][i].to]++;
if( cnt[V[top][i].to]>n)//入队次数大于n,代表有负权环
return 1;
}
}
}
}
return 0;
}
int main()
{
int f;
scanf("%d",&f);
while(f--)
{
for(int i=0; i<=2505; i++)V[i].clear();
scanf("%d%d%d",&n,&m,&w);
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&s,&e,&t);
V[s].push_back(Node(e,t));
V[e].push_back(Node(s,t));
}
for(int i=1; i<=w; i++)
{
scanf("%d%d%d",&s,&e,&t);
V[s].push_back(Node(e,-t));
}
if(spfa())
{
printf("YES\n");
}
else
printf("NO\n");
}
}