uva11478(spfa求负环)

这道题其实和uva11090类似,都是求负环,博主这里继续用spfa来写,需要注意的是,这里需要考虑0环,在一个环里,a边加一个数,b边减相同的数,到最后你会发现总和没变,在这里我想说每个顶点所连的边加减的数值随意,可以不相等

#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=505;
int n,m,l,r,mid;
int head[maxn],cnt[maxn],edge;
bool vis[maxn];
int dis[maxn];
struct Edgenode
{
    int to,next;
    int w;
};
Edgenode edges[maxn*maxn];
void add(int u,int v,int c)
{
    edges[edge].w=c;
    edges[edge].to=v;
    edges[edge].next=head[u];
    head[u]=edge++;
}
void init()
{
    memset(head,-1,sizeof(head));
    edge=0;
    l=1,r=0,mid=0;
}
bool spfa()
{
    queue<int>que;
    int u;
    for(int i=1; i<=n; i++)
    {
        dis[i]=INF;
        cnt[i]=0;
        que.push(i);
    }
    //dis[y]=0;
   // que.push(y);
    memset(vis,0,sizeof(vis));
    //vis[y]=1;
    while(!que.empty())
    {
        u=que.front();
        que.pop();
        vis[u]=false;
        for(int i=head[u]; i!=-1; i=edges[i].next)
        {
            int v=edges[i].to;
            int w=edges[i].w;
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                if(!vis[v])
                {
                    vis[v]=true;
                    que.push(v);
                    if(++cnt[v]>=n)
                        return 0;
                }
            }
        }
    }
    return 1;
}
bool check(int x)
{
    bool flag=0;
    for(int i=1; i<=n; i++)
        for(int k=head[i]; k!=-1; k=edges[k].next)
            edges[k].w-=x;
    //for(int i=1; i<=n; i++)//这次沿用上次的方法居然没过,看来还得刚开始把所有点加入队列
    {
        if(!spfa())//这块是把所有点找一遍,看看能否找到环
            flag=1;
    }
    for(int i=1; i<=n; i++)
        for(int k=head[i]; k!=-1; k=edges[k].next)
        {
            edges[k].w+=x;
        }
    return flag;
}
int main()
{
    int a,b,w;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&a,&b,&w);
            add(a,b,w);
            r=max(r,w);
        }
        if(!check(r+1))//还有这里就是如果我减掉最大值+1,还是不能构成负环,那么就说明无法成环
            printf("Infinite\n");
        else if(check(l))
        {
            printf("No Solution\n");
        }
        /*else//这里应该才是这个题标准的二分 { while(l<r) { mid=(r+l+1)/2; if(check(mid)) { r=mid-1; } else l=mid; } printf("%d\n",l); }*/
        else
        {
            while(l<=r)
            {
                mid=(r+l)/2;
                if(check(mid))
                {
                    r=mid-1;
                }
                else l=mid+1;
            }
            printf("%d\n",r);
        }

    }
    return 0;
}

你可能感兴趣的:(图论,uva)