1. 程式人生 > >洛谷 P2850 [USACO06DEC]蟲洞Wormholes 判負環

洛谷 P2850 [USACO06DEC]蟲洞Wormholes 判負環

blog 輸入 tdi 總數 進行 truct 是否 mes 發的

蟲洞(wormhole)

FJ 在農場上閑逛時,發現他的農場裏有很多蟲洞。蟲洞是一條特殊的有向路徑,當

FJ 從它的一頭走到另一頭後,他將被傳送到過去的某個時刻。FJ 的每個農場包括

N(1<=N<=500)塊按1..N 編號的草地、M(1<=M<=2500)條草地間的道路以及W(1<=W<=200)

個蟲洞。

FJ 一直以來就渴望進行時間旅行,於是他開始做如下的打算:從某塊草地出發,穿

過一些道路以及一些蟲洞,最終回到他出發的草地。這樣,他說不定能碰見過去的自

己:) 。

請你幫FJ 算一下,他是否可能找到這樣的一條路。當然,FJ 會給你他的所有

F(1<=F<=5)個農場的完整的地圖。沒有哪條道路上需要花的時間超過10,000 秒,同時,

也沒有哪個蟲洞能把FJ 帶回10,000 秒以前。

程序名: wormhole

輸入格式:

  • 第1 行: 一個正整數F,即農場總數。以下依次描述各個農場的地圖

  • 每個農場描述的第1 行:三個用空格隔開的整數,N、M 和W

  • 每個農場描述的第2..M+1 行:每行包含三個用空格隔開的整數S、E、T,表示

編號為S 的草地和編號為E 的草地邊有一條雙向道路,通過它所花費的時間為T 秒。兩

塊草地間可能有多條道路

  • 每個農場描述的第M+2..M+W+1 行:每行包含三個用空格隔開的整數S、E、T,

描述了一個起點編號為S、終點編號為E 的蟲洞。穿過這個蟲洞後,FJ 可以回到T 秒之

前 輸入樣例(wormhole.in):

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

輸入說明:

FJ 交給你兩個農場的地圖。第一個農場裏有三條道路以及一個蟲洞,第二個農場裏

有兩條道路和一個蟲洞。

輸出格式:

  • 第1..F 行: 對於每個農場,如果FJ 可以實現他回到過去的願望,輸出"YES",

否則輸出"NO"(不含引號)。

輸出樣例(wormhole.out):

NO
YES

輸出說明:

在農場1 中,FJ 無法完成他期望的時間旅行。

在農場2 中,FJ 可以沿路線1->2->3->1 旅行,這樣他能在離開1 號草地前一秒回

到1 號草地。當然,從這條路線上的其他草地出發,也能達到目的。

這道題簡單來說就是判斷圖內是否存在負環;

判斷負環方法:拓撲排序或spfa

spfa判斷負環:如果任意一條邊被修改大於n次,就代表這個圖內一定存在至少一個負環。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define man 1000010
 4 #define ll int
 5 struct edge 
 6 {
 7     int next,dis,to;
 8     }e[man<<2];
 9 ll head[man<<2],num=0,cnt[man<<1];
10 bool vis[man];
11 ll dis[man<<1],t,n,m,w;
12 inline void add(ll from,ll to,ll dis)
13 {
14     e[++num].next=head[from];
15     e[num].to=to;
16     e[num].dis=dis;
17     head[from]=num;
18     }
19 inline void clear()
20 {
21     memset(head,0,sizeof(head));
22     memset(e,0,sizeof(e));
23     memset(cnt,0,sizeof(cnt));
24     num=0;
25     }
26 inline bool spfa(ll s)
27 {
28     memset(vis,0,sizeof(vis));
29     memset(dis,0x7f,sizeof(dis));
30     queue<int >q;
31     q.push(s);dis[s]=0;vis[s]=1;
32     do
33     {
34         int u=q.front();q.pop();
35         vis[u]=0;
36         for(int i=head[u];i;i=e[i].next)
37         {
38             ll to=e[i].to;
39             if(dis[to]>dis[u]+e[i].dis)
40             {    dis[to]=dis[u]+e[i].dis;
41                 if(!vis[to])
42                 {
43                     q.push(to);
44                     vis[to]=1;
45                     cnt[to]++;
46                     }
47                 if(cnt[to]>n) return 1;
48                 }            
49             }
50         }while(q.size());
51     return 0;
52     }
53 int main()
54 {
55     ios::sync_with_stdio(false);
56     cin>>t;
57     while(t--)
58     {
59         clear();
60         cin>>n>>m>>w;
61         for(int i=1,x,y,z;i<=m;i++)
62         {    cin>>x>>y>>z;
63             add(x,y,z);add(y,x,z);
64             }
65         for(int i=1,x,y,z;i<=w;i++)
66         {    cin>>x>>y>>z;
67             add(x,y,-z);
68             }
69         if(spfa(1)==1) cout<<"YES"<<endl;
70         else cout<<"NO"<<endl;
71         }
72     return 0;
73     }

拓撲排序:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 int t,n,m,w,x,y,z,num=0,dis[10010];
 7 bool flag;
 8 struct star{
 9     int from,to,dis;
10 }e[10010];
11 void add(int from, int to, int dis){
12     e[++num].from=from;
13     e[num].to=to;
14     e[num].dis=dis;
15 }
16 bool topsort(){
17     memset(dis,0x7f,sizeof(dis));
18     dis[1]=0;   
19     for(int i=1;i<=n;i++){
20         flag=0;
21         for(int j=1;j<=num;j++)
22             if(dis[e[j].to]>dis[e[j].from]+e[j].dis){
23                 flag=1;
24                 dis[e[j].to]=dis[e[j].from]+e[j].dis;
25             }
26         if(!flag)return 0;
27     }
28     return 1;
29 }
30 int main(){
31     scanf("%d",&t);
32     for(int i=1;i<=t;i++){
33         num=0;
34         scanf("%d%d%d",&n,&m,&w);
35         for(int j=1;j<=m;j++){
36             scanf("%d%d%d",&x,&y,&z);
37             add(x,y,z);add(y,x,z);
38         }
39         for(int j=1;j<=w;j++){
40             scanf("%d%d%d",&x,&y,&z);
41             add(x,y,-z);
42         }
43         if(topsort())printf("YES\n");
44         else printf("NO\n");
45     }
46     return 0;
47 }

洛谷 P2850 [USACO06DEC]蟲洞Wormholes 判負環