[USACO06DEC]虫洞Wormholes (负环模板)

题意::问一个图是否存在负环,虫洞一边的权值为负

思路:

dfs版spfa判环根据:若一个节点出现2次及以上,则存在负环.(你可以假想一下,当一个点被搜过时,再次深搜的话还能搜索到那不就说明存在负环嘛可能解释的不好,请见谅)
  {补充bfs版本:若一个节点入队列的次数超过n,则存在负环.}
  如果是bfs来实现的话,果断到达上限(T-L-E),而dfs版的话,就相对快一些.
  对于本题的强大数据来说,还需加入一定的优化:
  由于是负环,所以无需像一般的spfa一样初始化为极大的数,只需要初始化为0就够了(可以减少大量的搜索,但要注意最开始时for一遍)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn=505;
 5 int inf=0xfffffff;
 6 int dis[maxn];
 7 bool ant[maxn];
 8 int n,m,w,flag;
 9 struct node
10 {
11     int to,val;
12     node(){}
13     node(int xx,int yy):to(xx),val(yy){}
14 };
15 vector<node> v[maxn];//本人喜欢用邻接表
16 void init()
17 {
18     for(int i=1;i<=n;i++)
19     {
20         v[i].clear();
21         dis[i]=0;
22         ant[i]=0;
23     }
24 }
25 void dfs_spfa(int x)
26 {
27     if(ant[x]){//只要有一个点走过两次说明存在负环,即可退出,并释放标记
28         ant[x]=0;
29         flag=1;
30         return ;
31     }
32     ant[x]=1;//标记表示走过
33     for(int i=0;i<v[x].size();i++)
34     {
35         node p=v[x][i];
36         if(dis[p.to]>dis[x]+p.val){
37             dis[p.to]=dis[x]+p.val;
38             dfs_spfa(p.to);
39             if(flag==1){
40                 ant[x]=0;return ;//存在负环的话就层层退出
41             }
42         }
43     }
44     ant[x]=0;//再次释放标记
45 }
46 int main()
47 {
48     int t;
49     scanf("%d",&t);
50     while(t--)
51     {
52         scanf("%d%d%d",&n,&m,&w);
53         init();
54         for(int i=1;i<=m;i++)
55         {
56             int a,b,c;
57             scanf("%d%d%d",&a,&b,&c);
58             v[a].push_back(node(b,c));
59             v[b].push_back(node(a,c));
60         }
61         for(int i=1;i<=w;i++)
62         {
63             int a,b,c;
64             scanf("%d%d%d",&a,&b,&c);
65             v[a].push_back(node(b,-c));
66         }
67         flag=0;
68         for(int i=1;i<=n;i++)
69         {
70             dfs_spfa(i);
71             if(flag){break;}
72         }
73         if(flag){
74             cout<<"YES"<<endl;
75         }
76         else{
77             cout<<"NO"<<endl;
78         }
79     }
80     return 0;
81 }

 留给自己做模板用5555

在给一个模板

 1 bool spfa(int u)
 2 {  
 3     vis[u] = true;  
 4     int i;  
 5     for(i = head[u]; i; i = e[i].next)
 6     {    
 7         int v = e[i].to, w = e[i].w;    
 8         if(dis[v] > dis[u] + w)
 9         {      
10             dis[v] = dis[u] + w;      
11             if(vis[v]) return false;      
12             if(!spfa(v)) return false;    
13         }  
14     }  
15     vis[u] = false;  
16     return true;
17 }

 

posted @ 2019-09-10 17:09  sj-_-js  阅读(303)  评论(0编辑  收藏  举报