poj 3259 Wormholes

来源:互联网 发布:编程证明哥德巴赫猜想 编辑:程序博客网 时间:2024/05/19 05:34

本题链接:点击打开链接

本题大意:

        本题题意看了大半天也是没弄明白 -_-|||,然后去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 5050using 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");elseprintf("NO\n");}return 0;}

0 0
原创粉丝点击