标签:
本题链接:点击打开链接
本题大意:
本题题意看了大半天也是没弄明白 -_-|||,然后去poj原题讨论区看看,终于弄懂了题目。题意是:先输入一个F,代表有F组测试数据;每组测试数据先输入N、M、W,表示有N个点,M条无向边,W条有向边,并且,该有向边的权值应取负值(输入的是正数),接下来输入M+W条边,每条边都是两个顶点+权值;然后让判断能否产生环,若能,输出YES,否则输出NO。
解题思路:
判断有负权值的边就不能使用dijkstra算法和prim算法了,本题可使用SPFA算法,首先用链表建图,使用mark[]数组标记点是否使用,使用used[]数组记录点入队的次数,SPFA算法大致与BFS搜索的步骤相似,只是要将已入队列的标记过的点,在取出队首时,要取消其标记。每次入队时,将入队的点对应的used值自加一次;判断有环的条件是有点进队列次数超过或等于点的总数N,即有点对应的used值 >= N;出现此情况说明出现了环。具体请参考代码:
#include<stdio.h> #include<string.h> #include<queue> #define INF 0x3f3f3f3f #define MAXN 550 #define MAXM 5050 using namespace std; int head[MAXN]; int dis[MAXN]; int mark[MAXN]; int used[MAXN]; struct node{ int from,to,val,next; }; node edge[MAXM]; int num,N,M,W; void getmap(int u,int v,int w) { node e={u,v,w,head[u]}; edge[num]=e; head[u]=num++; } bool SPFA(int s) { queue<int>q; memset(mark,0,sizeof(mark)); memset(dis,INF,sizeof(dis)); memset(used,0,sizeof(used)); q.push(s); mark[s]=1; dis[s]=0; used[s]++; while(!q.empty()) { int top=q.front(); q.pop(); mark[top]=0; for(int i=head[top];i!=-1;i=edge[i].next) { int u=edge[i].to; if(dis[u]>dis[top]+edge[i].val) { dis[u]=dis[top]+edge[i].val; if(!mark[u]) { mark[u]=1; q.push(u); used[u]++; if(used[u]>=N) return true; } } } } return false; } int main() { int F; int S,E,T; scanf("%d",&F); while(F--) { scanf("%d%d%d",&N,&M,&W); memset(head,-1,sizeof(head)); num=0; for(int i=0;i<M;i++) { scanf("%d%d%d",&S,&E,&T); getmap(S,E,T); getmap(E,S,T); } for(int i=0;i<W;i++) { scanf("%d%d%d",&S,&E,&T); getmap(S,E,-T); } if(SPFA(1)) printf("YES\n"); else printf("NO\n"); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/lsgbb/article/details/47783185