POJ1364 SPFA

差分约束

题意:
给出n代表一个序列的长度,给出m个约束条件(si , ni , oi , ki),若oi为gt,则序列从位置si~(si+ni)的和大于ki,若oi为lt,则和小于ki。问是否存在这样的序列使得约束条件成立。


转化为最短路问题:
当 oi 为 gt 时,S(si-1) - S(si+ni) ≤ -k-1
当 oi 为 lt 时, S(si+ni) - S(si-1) ≤ k-1
判断图上是否存在负环

注意点

1.将所有点入队(将图连通)
2.负环判断改成大于入队n+1次
3.顶点从0-n

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int maxn = 1000 + 10;
const int INF = 0x3f3f3f3f;

struct edge{int to, next, cost;};
edge e[maxn];
int head[maxn];
int dist[maxn];
int n, m, cnt;

void add_edge(int x, int y, int w)
{
    e[cnt].to = y;
    e[cnt].next = head[x];
    e[cnt].cost = w;
    head[x] = cnt;
    cnt++;
}

bool spfa(int s)
{
    for(int i = 0; i <= n; i++) dist[i] = 0;
    int vis[maxn]; memset(vis, 0, sizeof(vis));
    bool inque[maxn]; memset(inque, false, sizeof(inque));
    queue<int> q;
    for(int i = 0; i <= n; i++){
        q.push(i);vis[i]++; inque[i] = true;
    }
    while(!q.empty()){
        int cur = q.front(); q.pop(); inque[cur] = false;
        for(int i = head[cur]; ~i; i = e[i].next){
            if(dist[e[i].to] > dist[cur] + e[i].cost){
                dist[e[i].to] = dist[cur] + e[i].cost;
                if(!inque[e[i].to]){
                    q.push(e[i].to); inque[e[i].to] = true;
                    if(++vis[e[i].to] > n+1) return false;
                }

            }
        }
    }
    return true;
}

int main()
{
    cnt =0;
    while(cin>>n){
        if(!n) break;
        cin>>m;
        memset(head, -1, sizeof(head));
        for(int i = 0; i < m; i++){
            int x, y, w; string t;
            cin>>x>>y>>t>>w;
            if(t == "gt") add_edge(x-1, x+y, -w-1);
            else add_edge(x+y, x-1, w-1);
        }

        if(!spfa(0)) cout<<"successful conspiracy"<<endl;
        else{
            cout<<"lamentable kingdom"<<endl;
        }
    }
    return 0;
}

posted @ 2017-07-05 11:10  />.<\  阅读(92)  评论(0编辑  收藏  举报