POJ_3259_Wormholes

本题目实际上就是判断是否存在带负权回路,我用的是SPFA算法判断,原理是:如果存在负权值回路,则存在某顶点入队次数count1[v]>N(总的顶点数),所以只需添加一个数组记录顶点入队次数就行了。

View Code
  1 #include<iostream>
  2 #include<cstdio> 
  3 #include<cstring> 
  4 using namespace std;
  5 #include<queue>
  6 #define MAXN 600 
  7 #define INF 100000000
  8 struct node
  9 {
 10     int to;
 11     int w;
 12     node * next;    
 13 };
 14 
 15 node * List[MAXN];
 16 int path[MAXN];
 17 int dist[MAXN];
 18 int vis[MAXN];
 19 int count1[MAXN]; 
 20 int n,m,w; 
 21 
 22 void SPFA(int v0)
 23 {
 24     memset(count1,0,sizeof(count1));
 25     memset(vis,0,sizeof(vis)); 
 26         int u;
 27         for(int i=1;i<=n;i++)
 28         {
 29                 dist[i]=INF;
 30                 path[i]=v0;
 31                 vis[i]=0;    
 32         }
 33         dist[v0]=0;
 34         path[v0]=v0;
 35         vis[v0]=1;
 36         node *temp;
 37         queue<int> q;
 38         q.push(v0);
 39         count1[v0]++; 
 40         while(!q.empty())
 41         {
 42             u=q.front();
 43             q.pop();
 44             vis[u]--; 
 45             temp=List[u];
 46             if(count1[u]>n)
 47             {
 48                printf("YES\n");
 49                return ;    
 50             } 
 51             while(temp!=NULL)
 52             {
 53                 int v=temp->to;
 54                 if(dist[v]>dist[u]+temp->w)
 55                 {
 56                         dist[v]=dist[u]+temp->w;
 57                         path[v]=u;
 58                         if(!vis[v])
 59                         {
 60                             q.push(v);
 61                             vis[v]++;
 62                             count1[v]++;    
 63                         }    
 64                 }
 65               temp=temp->next;    
 66             }    
 67         }
 68         
 69         printf("NO\n");            
 70 }
 71 void show(int i)
 72 {
 73     if(i==0)
 74     return;
 75     show(path[i]);
 76     printf("%d->",i);    
 77 }
 78 int main()
 79 {
 80     int T,u,v,ww;
 81     scanf("%d",&T);
 82     while(T--)
 83     {
 84         memset(List,0,sizeof(List)); 
 85           node * temp; 
 86         scanf("%d%d%d",&n,&m,&w);
 87             for(int i=0;i<m;i++)
 88             {
 89                 scanf("%d%d%d",&u,&v,&ww);
 90                 temp=new node;
 91                 temp->to=v;
 92                 temp->w=ww;
 93                 temp->next=NULL;
 94                 if(List[u]==NULL) List[u]=temp;
 95                 else
 96                 {
 97                     temp->next=List[u];
 98                     List[u]=temp;    
 99                 }
100                 temp=new node;
101                 temp->to=u;
102                 temp->w=ww;
103                 temp->next=NULL;
104                 if(List[v]==NULL) List[v]=temp;
105                 else
106                 {
107                     temp->next=List[v];
108                     List[v]=temp;    
109                 }
110                         
111             }    
112             for(int i=0;i<w;i++)
113             {
114                 scanf("%d%d%d",&u,&v,&ww);
115                 temp=new node;
116                 temp->to=v;
117                 temp->w=-ww;
118                 temp->next=NULL;
119                 
120                 if(List[u]==NULL) 
121                 List[u]=temp;
122                 else
123                 {
124                     temp->next=List[u];
125                     List[u]=temp;    
126                 }
127             }
128     SPFA(1); 
129     } 
130     system("pause");    
131     return 0;    
132 }

 

转载于:https://www.cnblogs.com/myacm/archive/2012/08/10/2631442.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值