http://poj.org/problem?id=3259

题意 : 农夫约翰农场里发现了很多虫洞,他是个超级冒险迷,想利用虫洞回到过去,看再回来的时候能不能看到没有离开之前的自己,农场里有N块地,M条路连接着两块地,W个虫洞,连接两块地的路是双向的,而虫洞是单向的,去到虫洞之后时间会倒退T秒,如果能遇到离开之前的自己就输出YES,反之就是NO。

样例解释 : 

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

第一行中的2代表有两组测试数据,第一组测试数据中,3,3,1代表着有3块地,3条路,1个虫洞,下面三行代表着编号几到几的权值是几,最后一行代表的是通过虫洞去到目的地时间倒退了t秒

思路 : 这个题因为去到虫洞时间会倒退,而走农场之间相连的路又会花掉时间,明显是判断有没有负环,只要有负环,他只要一直走就能回到过去,典型的Bellman-Ford做法,本题采用的是spfa做法。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include<iostream>
  5 using namespace std;
  6 
  7 const int maxn = 1011;
  8 const int maxm = 10011;
  9 const int oo = 1<<28;
 10 struct node
 11 {
 12     int u;
 13     int v;
 14     int w;
 15     int next;
 16 } edge[maxm];
 17 int dis[maxn];
 18 int cnt;
 19 int N,M,T;
 20 int head[maxn];
 21 bool vis[maxn];
 22 queue<int>qu;
 23 int count[maxn];
 24 void add(int u, int v, int w)
 25 {
 26     edge[cnt].u = u;
 27     edge[cnt].v = v;
 28     edge[cnt].w = w;
 29     edge[cnt].next = head[u];
 30     head[u] = cnt++;
 31 }
 32 
 33 int spfa(int s)
 34 {
 35     memset(count,0,sizeof(count));
 36     for(int i = 1; i <= N; i++)
 37     {
 38         dis[i] = oo;
 39         vis[i] = false;
 40     }
 41     dis[s] = 0;
 42     qu.push(s);
 43     vis[s] = true;
 44     while(!qu.empty())
 45     {
 46         int u = qu.front();
 47         qu.pop();
 48         vis[u] = false;
 49         for(int i = head[u]; i != -1; i = edge[i].next)
 50         {
 51             int v = edge[i].v;
 52             if(dis[u]+edge[i].w < dis[v])
 53             {
 54                 dis[v] = dis[u]+edge[i].w;
 55                 if(++count[v] > N) return 0;
 56                 if(!vis[v])
 57                 {
 58                     vis[v] = true;
 59                     qu.push(v);
 60                 }
 61             }
 62         }
 63     }
 64     return 1;
 65 }
 66 
 67 void init()
 68 {
 69     cnt = 0;
 70     memset(head, -1, sizeof(head));
 71 }
 72 
 73 int main()
 74 {
 75     int n ;
 76     scanf("%d",&n);
 77     while(n--)
 78     {
 79         init();
 80         scanf("%d %d %d",&N,&M,&T);
 81         int u, v, w;
 82         for(int i = 1; i <= M; i++)
 83         {
 84             scanf("%d %d %d", &u, &v, &w);
 85             add(u, v, w);
 86             add(v, u, w);
 87         }
 88         for(int i = 1 ; i <= T ; i++)
 89         {
 90             cin>>u>>v>>w;
 91             add(u,v,(-1*w));
 92         }
 93         int flag = spfa(1);
 94         if(flag == 0)
 95         cout<<"YES"<<endl;
 96         else
 97         cout<<"NO"<<endl;
 98     }
 99     return 0;
100 }
View Code

Bellman-Ford算法及其改进---SPFA算法可以参照下边这个博客

 http://hi.baidu.com/laozhonggu/item/30a3f90d81b01fc975cd3c28

posted on 2013-08-15 10:16  枫、  阅读(237)  评论(0编辑  收藏  举报