POJ 1364 差分约束

来源:互联网 发布:淘宝直播回放下载 编辑:程序博客网 时间:2024/06/06 00:55

题意:给你一个n和m,接下来m行,每行描述了一个不等式,每行有个a,b,一个符号,c,如果字符串为gt,就代表某个数列的[a,b]的和大于c,如果字符串为lt,就代表某个数列的[a,b]的和小于c,然后问你上述条件能不能同时成立,不能输出successful conspiracy,能输出lamentable kingdom。

思路:将这些条件都转化为标准的差分约束的不等式,然后建图,判断有没有负环,有就是不能,没有就是可以。

说下我之前纠结的为什么有负环就证明不能满足条件,假如有三条边a->b = x,b->c = y,c->a = z,转化成不等式就是sa<=sc+z,sc<=sb+y,sb<=sa+x,然后把左右相加,约掉一堆东西,得到0<=x+y+z,如果出现负环,那么x+y+z<0可以得出不满足条件。。也许是悟性太差,不能一下理解。。所以自己小证了一下=。=

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std;const int maxn = 200;const int inf = 0x3f3f3f3f;int n,m,all;int node[maxn],top;struct Side{    int v,w,next;}side[maxn];void add_side(int u,int v,int w){    side[top] = (Side){v,w,node[u]};    node[u] = top++;}int dis[maxn],vis[maxn],in[maxn];bool done[maxn];queue<int>q;int spfa(int s){    memset(dis,inf,sizeof(dis));    memset(vis,0,sizeof(vis));    memset(in,0,sizeof(in));    dis[s] = 0;in[s] = 1;    q.push(s);    while(!q.empty()){        int u = q.front();q.pop();        vis[u] = 0;done[u] = 1;        for(int i = node[u];i != -1;i = side[i].next){            int v = side[i].v;            if(dis[v] > dis[u] + side[i].w){                dis[v] = dis[u] + side[i].w;                if(!vis[v]){                    in[v] ++;                    if(in[v] > all)return -1;                    vis[v] = 1;                    q.push(v);                }            }        }    }    return 1;}int main(){    //freopen("in.txt","r",stdin);    while(~scanf("%d",&n),n){        memset(node,-1,sizeof(node));        memset(done,false,sizeof(done));        top = 0;        scanf("%d",&m);        int nn[maxn] = {0};        all = 0;//记录共有几个节点        while(m--){            int a,b,c;            char op[5];            scanf("%d %d %s %d",&a,&b,op,&c);            if(op[0] == 'g'){                add_side(a+b,a-1,-1-c);                nn[a-1] = nn[a + b] = 1;            }            else if(op[0] == 'l'){                add_side(a-1,b+a,c-1);                nn[a + b] = nn[a - 1] = 1;            }        }        int ans;        for(int i = 0;i <= n;i ++)            if(nn[i])all ++;        for(int i = 0;i <= n;i ++)            if(nn[i]&&done[i] == false){                ans = spfa(i);//说不定不连通。。                if(ans == -1)break;            }        if(ans == -1)printf("successful conspiracy\n");        else printf("lamentable kingdom\n");    }    return 0;}


0 0
原创粉丝点击