[POJ1364]King(差分约束系统)

题目描述

传送门

题解

由于是连续的序列,想到转化成前缀和相减的形式。
由于约束值都是整数,所以小于/大于一个数可以转化为小于等于/大于等于这个数减1或加1;
这样我们就十分巧妙地把它转换成了差分约束系统的基本模型。
那么剩下的就是spfa了。
注意此题可能有好几个连通块,所以要加超级源。并且spfa要判断负环。

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;

const int max_n=105;
const int max_m=105;
const int max_M=max_m*10;
const int max_e=max_M*2;

char s[5];
int n,m,st,cnt,w,u,t;
int tot,next[max_e],point[max_n],v[max_e],c[max_e];
int dis[max_n],insert[max_n];
bool vis[max_n];
queue <int> q;

inline void clear(){
    tot=0;
    memset(next,0,sizeof(next));
    memset(point,0,sizeof(point));
    memset(v,0,sizeof(v));
    memset(c,0,sizeof(c));
    memset(insert,0,sizeof(insert));
    memset(dis,0,sizeof(dis));
    memset(vis,0,sizeof(vis));
}

inline void addedge(int x,int y,int z){
    ++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
}

inline bool spfa(){
    memset(dis,0x7f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[n+1]=0;
    vis[n+1]=true;
    while (!q.empty()) q.pop();
    q.push(n+1);
    insert[n+1]++;

    while (!q.empty()){
        int now=q.front(); q.pop();
        vis[now]=false;
        for (int i=point[now];i;i=next[i])
          if (dis[v[i]]>dis[now]+c[i]){
            dis[v[i]]=dis[now]+c[i];
            if (!vis[v[i]]){
                vis[v[i]]=false;
                q.push(v[i]);
                insert[v[i]]++;
                if (insert[v[i]]>n+3) return false;
            }
          }
    }
    return true;
}

int main(){
    while (~scanf("%d%d",&n,&m)){
        if (!n) break;

        clear();

        for (int i=1;i<=m;++i){
            scanf("%d%d",&st,&cnt);
            scanf("%s",s);
            scanf("%d",&w);
            if (s[0]=='g'){
                w++;
                w=-w;
                u=st+cnt;
                t=st-1;
                addedge(u,t,w);
            }
            else{
                w--;
                u=st-1;
                t=st+cnt;
                addedge(u,t,w);
            }
        }
        for (int i=0;i<=n;++i)
          addedge(n+1,i,0);

        bool pd=spfa();

        if (pd) printf("lamentable kingdom\n");
        else printf("successful conspiracy\n");
    }
}

总结

①添加超级源之后spfa一定是从超级源开始跑。
②spfa判断负环的条件是某一个点入队超过n次。(可以稍微大一点)

你可能感兴趣的:(poj,差分约束)