bzoj 1715(spfa 判断负环)

1715: [Usaco2006 Dec]Wormholes 虫洞

Time Limit: 5 Sec   Memory Limit: 64 MB
Submit: 605   Solved: 345
[ Submit][ Status][ Discuss]

Description

John在他的农场中闲逛时发现了许多虫洞。虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前)。John的每个农场有M条小路(无向边)连接着N (从1..N标号)块地,并有W个虫洞。其中1<=N<=500,1<=M<=2500,1<=W<=200。 现在John想借助这些虫洞来回到过去(出发时刻之前),请你告诉他能办到吗。 John将向你提供F(1<=F<=5)个农场的地图。没有小路会耗费你超过10000秒的时间,当然也没有虫洞回帮你回到超过10000秒以前。

Input

* Line 1: 一个整数 F, 表示农场个数。

* Line 1 of each farm: 三个整数 N, M, W。

* Lines 2..M+1 of each farm: 三个数(S, E, T)。表示在标号为S的地与标号为E的地中间有一条用时T秒的小路。

* Lines M+2..M+W+1 of each farm: 三个数(S, E, T)。表示在标号为S的地与标号为E的地中间有一条可以使John到达T秒前的虫洞。

Output

* Lines 1..F: 如果John能在这个农场实现他的目标,输出"YES",否则输出"NO"。

Sample Input

2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8

Sample Output

NO

YES


解题思路:首先先构图(有重边),黑洞赋予负值(注意是有向边),然后判断是否有负环。


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int F;
int n,m,w;
int dis[501];
bool b[501];
int q[1000000];
int f[501][501];
int degree[501];


inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}


int main()
{
   F=read();
   for (int u=1;u<=F;++u)
    {
    n=read(); m=read(); w=read();
        memset(f,0x7f,sizeof(f));
      for (int i=1;i<=m;++i)
    {
      int s,e,t;
      s=read(); e=read(); t=read();
      if (s!=e) 
       {
        f[s][e]=min(f[s][e],t); f[e][s]=min(f[e][s],t);
       }
}
for (int i=1;i<=w;++i)
{
int s,e,t;
s=read(); e=read(); t=read();
if (s==e) continue;
f[s][e]=min(f[s][e],-t);
}
memset(dis,0x7f,sizeof(dis));
bool mg=false;
memset(degree,0,sizeof(degree));
memset(b,true,sizeof(b)); 
dis[1]=0; b[1]=false; int tail=1,head=0; q[1]=1; ++degree[1];
while (head<tail)
{
++head;
   for (int i=1;i<=n;++i)
    if (f[q[head]][i]<1000000)
{
    if (f[q[head]][i]+dis[q[head]]<dis[i])
    {
    dis[i]=f[q[head]][i]+dis[q[head]];
    if (b[i])
    {
    b[i]=false;
    ++degree[i]; ++tail; q[tail]=i;
    if (degree[i]>n) {mg=true;break;}
  }
 }
}
if (mg) break;
b[q[head]]=true;
}
if (mg) printf("YES\n");else printf("NO\n");
}
}

你可能感兴趣的:(bzoj 1715(spfa 判断负环))