poj 2983 差分约束

思路:

设dis[i]为标号为i的点到0号点的距离。对于P A B X,我们能得到等式dis[a]-dis[b]=x,那么可以化为两个不等式dis[a]-dis[b]>=x和dis[b]-dis[a]>=-x。这样就可以建两条边。V A B的话,我们知道dis[a]-dis[b]>=1,可以建一条边。这些边建起来后,图可能是一个离散的图,那么我们就定义一个超级源点连接所有的点,权值为0.进行求最长路时,只要判断是否有正圈存在,正圈的含义是绕着这个圈使每个点的dis值不断增大。用bellman-ford算法就行。还有一个笨的方法,其实是卡数据的,我们就用spfa求最长路,若循环次数超过一定,我们就认为有正圈存在。

这个是用bellman_ford做的:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define inf 1<<30
#define Maxn 10010
#define Maxm 500000
using namespace std;
int dis[Maxn],vi[Maxn],index[Maxn],e,Que[1000010],num=0,n;
struct Edge{
    int to,next,val,from;
}edge[Maxm];
void init()
{
    int i,j;
    for( i=0;i<=Maxn-1;i++)
        dis[i]=-inf;
    memset(vi,0,sizeof(vi));
    memset(index,-1,sizeof(index));
    e=0;
    num=0;
}
void addedge(int from,int to,int val)
{
    edge[e].from=from;
    edge[e].to=to;
    edge[e].val=val;
    edge[e].next=index[from];
    index[from]=e++;
}
int bellman_ford()
{
    int i,j,temp,flag;
    for(i=1;i<=n;i++)
    {
        flag=1;
        for(j=0;j<e;j++)
        {
            temp=edge[j].from;
            if(dis[temp]+edge[j].val>dis[edge[j].to])
            {
                dis[edge[j].to]=dis[temp]+edge[j].val;
                flag=0;
            }
        }
        if(flag)
            return 1;
    }
    return 0;
}
int main()
{
    int i,j,a,b,c,m;
    char str[2];
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        //cout<<"ok"<<endl;
        for(i=1;i<=m;i++)
        {
            scanf("%s",&str);
            if(str[0]=='P')
            {
                scanf("%d%d%d",&a,&b,&c);
                addedge(b,a,c);
                addedge(a,b,-c);
            }
            else
            {
                scanf("%d%d",&a,&b);
                addedge(b,a,1);
            }
        }
        for(i=1;i<=n;i++)
            addedge(0,i,0);
        if(bellman_ford())
            printf("Reliable
");
        else
            printf("Unreliable
");
    }
    return 0;
}
View Code

给个卡数据的spfa:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define inf 1<<30
#define Maxn 10010
#define Maxm 500000
using namespace std;
int dis[Maxn],vi[Maxn],index[Maxn],e,Que[1000010],num=0;
struct Edge{
    int to,next,val;
}edge[Maxm];
void init()
{
    int i,j;
    for( i=0;i<=Maxn-1;i++)
        dis[i]=-inf;
    memset(vi,0,sizeof(vi));
    memset(index,-1,sizeof(index));
    e=0;
    num=0;
}
void addedge(int from,int to,int val)
{
    edge[e].from=from;
    edge[e].to=to;
    edge[e].val=val;
    edge[e].next=index[from];
    index[from]=e++;
}
int spfa()
{
    int i,j,temp,head,rear;
    head=rear=0;
    Que[head++]=0;
    dis[0]=0;
    //cout<<maxn<<endl;
    while(head!=rear)
    {
        temp=Que[rear++];
        //cout<<temp<<endl;
        vi[temp]=0;
        for(i=index[temp];i!=-1;i=edge[i].next)
        {
            int now=edge[i].to;
            if(dis[now]<dis[temp]+edge[i].val)
            {    
                num++;
                if(num>500000)
                    return 0;
                if(edge[i].val<0)
                {
                    dis[temp]+edge[i].val+graphic[now][temp]
                }
                dis[now]=dis[temp]+edge[i].val;
                if(!vi[now])
                    Que[head++]=now;
                vi[now]=1;
            }
        }
    }
    return 1;
}
int main()
{
    int i,j,n,a,b,c,m;
    char str[2];
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        //cout<<"ok"<<endl;
        for(i=1;i<=m;i++)
        {
            scanf("%s",&str);
            if(str[0]=='P')
            {
                scanf("%d%d%d",&a,&b,&c);
                addedge(b,a,c);
                addedge(a,b,-c);
            }
            else
            {
                scanf("%d%d",&a,&b);
                addedge(b,a,1);
            }
        }
        for(i=1;i<=n;i++)
            addedge(0,i,0);
        if(spfa())
            printf("Reliable
");
        else
            printf("Unreliable
");
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/wangfang20/p/3197606.html