poj2983

题意:给出两种关于防御站位置的信息,一种是确切的信息,P A B X,表示a在b北面x距离的地方,另一种是V A B,表示只知道A在B的北面。问这些信息有没有矛盾。

分析:差分约束。第一种记为A-B>=X && A-B<=X,第二种记为A-B>=0,用SPFA求得解,则没有矛盾,否则就有矛盾。

#include <iostream>
#include <stdio.h>
#include <queue>
using namespace std;
const int N=1001;
const int E=2*100000+1000;
const int inf=10000000;
struct edge{
    int to,w,next;
};
int adj[N];
edge e[E];//存放顶点的所有邻接边
bool visit[N];
int d[N];
/*记录节点更新的次数,如果超过n次,说明存在回路
由于约束图中含有n+1个顶点,所以每个顶点被松弛的次数不能能超过n
*/
int cnt[N];
int edge_num=0,n=0,m=0;
bool spfa()
{
    int s,u,v,i,w;
    s=0;
    queue<int> q;
    for(i=0;i<=n;i++)
        visit[i]=false;
    for(i=0;i<=n;i++)
        cnt[i]=0;
    visit[s]=true;
    q.push(s); //将源点加入到队列中
    while(!q.empty())
    {
        u=q.front();
    //    cout<<"出队:"<<u<<endl;
        q.pop();
        visit[u]=false;
        //遍历u的所有邻接边
        for(i=adj[u];i!=-1;i=e[i].next)
        {
            v=e[i].to;
            w=e[i].w;
    //        cout<<"v"<<v<<endl;
            if(d[u]+w < d[v])
            {
                d[v]=d[u]+w;
                if(!visit[v])
                {
                    visit[v]=true;
                    q.push(v);
                    cnt[v]++;
                    if(cnt[v]>n) //更新不超过n,有n+1个顶点,一开始写成>=n了
                    {
                    //    delete []visit;
                        return false;
                    }
                }
            }
        }
    }
    return true;
}
int main()
{
    char ch;
    int i,u,v,w;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        edge_num=0;
        for(i=0;i<=n;i++)
        {
            adj[i]=-1;
            d[i]=inf;
        }
        d[0]=0;
        for(i=0;i<m;i++)
        {
            cin>>ch;
            if(ch == 'P')
            {
                scanf("%d%d%d",&u,&v,&w);
                e[edge_num].to=u;
                e[edge_num].w=w;
                e[edge_num].next=adj[v];
                adj[v]=edge_num++;

                e[edge_num].to=v;
                e[edge_num].w=(-1)*w;
                e[edge_num].next=adj[u];
                adj[u]=edge_num++;
            }
            else
            {
                //x1-x2>=1,转化为约束条件为x2-x1<=-1
                scanf("%d%d",&u,&v);
                e[edge_num].to=v;
                e[edge_num].w=-1;
                e[edge_num].next=adj[u];
                adj[u]=edge_num++;
            }
        }
        //添加源点到其他顶点的边,权值为0
        for(i=1;i<=n;i++)
        {
            e[edge_num].to=i;
            e[edge_num].w=0;
            e[edge_num].next=adj[0];
            adj[0]=edge_num++;
        }
        if(!spfa())
            printf("Unreliable\n");
        else
            printf("Reliable\n");
    }
    return 0;
}

 

posted @ 2013-05-02 01:05  Hogg  阅读(753)  评论(0编辑  收藏  举报