POJ2679 SPFA求负环

来源:互联网 发布:js中currenttarget 编辑:程序博客网 时间:2024/06/05 05:15
SPFA求负环
注意事项:
1. 不要让一个点出队n次就算负环,如果只有一个点呢?出队n+1次费不了多少时间。
2. 从终点往回遍历不到的点即便有负环也无所谓,因为它根本无法在s → t的路径上累加负权值。
3. 此题注意删边方法。
#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#define N 3000#define M 101000using namespace std;//只能走权值最小的边 struct Syndra{int u,v,w,len,next;}e[M];int head[N],cnt;int dist[N],len[N],visit[N],s,t,n,m;int mini[N],able[N],num[N];void add(int u,int v,int w,int len){cnt++;e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;e[cnt].len=len;e[cnt].next=head[u];head[u]=cnt;}void spfa(){int i,j,k,u,v;queue<int> q;memset(dist,0x3f,sizeof(dist));memset(visit,0,sizeof(visit));memset(len,0x3f,sizeof(len));memset(num,0,sizeof(num));q.push(s);dist[s]=len[s]=0;visit[s]=1;while(!q.empty()){u=q.front();q.pop();visit[u]=0;if(!able[u])continue;num[u]++;if(num[u]>n){printf("UNBOUND\n");return;}for(i=head[u];i+1;i=e[i].next){v=e[i].v;if(!able[v])continue;if(e[i].w>mini[u])continue;if(dist[v]>dist[u]+e[i].w){dist[v]=dist[u]+e[i].w;len[v]=len[u]+e[i].len;if(!visit[v]){visit[v]=1;q.push(v);}}else if(dist[v]==dist[u]+e[i].w){if(len[v]>len[u]+e[i].len){len[v]=len[u]+e[i].len;if(!visit[v]){visit[v]=1;q.push(v);}}}}}if(dist[t]==0x3f3f3f3f){printf("VOID\n");return ;}else{printf("%d %d\n",dist[t],len[t]);return ;}}char a,b,c;void dfs(int x){int i;if(able[x])return ;able[x]=1;for(i=head[x];i+1;i=e[i].next){if(e[i^1].w==mini[e[i].v])dfs(e[i].v);}}void build(){int i,j,k;cnt=-1;memset(num,0,sizeof(num));memset(able,0,sizeof(able));memset(head,-1,sizeof(head));memset(mini,0x3f,sizeof(mini));for(i=1;i<=m;i++){int u,v,w1,l,w2;scanf(" %c%d%c%d%c%d%c%d%c%d%c",&a,&u,&a,&v,&a,&w1,&a,&l,&a,&w2,&a);add(u,v,w1,l);add(v,u,w2,l);mini[u]=min(mini[u],w1);mini[v]=min(mini[v],w2);}dfs(t);}int main(){//freopen("test.in","r",stdin);while(scanf("%d%d%d%d",&n,&m,&s,&t)!=EOF){build();spfa();}return 0;}


0 0
原创粉丝点击