2014 Super Training #6 B Launching the Spacecraft --差分约束

原题:ZOJ 3668 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3668

典型差分约束题。

将sum[0] ~ sum[n] 作为节点,A<=sum[R]-sum[L-1]<=B可以分别建边:

x(L-1)-->xR  w = B

xR --> x(L-1)  w = -A

注意还有 -10000<=sum[i]-sum[i-1]<=10000 (for i in (2,n)),所以相邻点之间还要建边,(WA了很多次)这样的话就不用另加节点来使联通了,因为必会连通。如果出现负环,则无解。

用SPFA求最短路并判负环,求出的节点的dis[i]如果为INF,则任意取值(事实上此题不会),否则dis[i]就是sum[i],然后根据sum数组两两之间差值来求出a[i]。

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <vector>

#include <map>

#include <queue>

#define Mod 1000000007

using namespace std;

#define N 10017



vector<pair<int,int> > G[N];

int dis[N],inq[N],cnt[N];

int sum[N];

int n,m;

queue<int> que;



bool SPFA(int s)

{

    int u,v,i,w;

    for(i=0;i<=n;i++)

    {

        inq[i] = 0;

        dis[i] = Mod;

        cnt[i] = 0;

    }

    while(!que.empty())

        que.pop();

    que.push(s);

    dis[s] = 0;

    cnt[s] = 1;

    inq[s] = 1;

    //for(i=0;i<=n;i++)

        //que.push(i);

    while(!que.empty())

    {

        u = que.front();

        que.pop();

        inq[u] = 0;

        for(i=0;i<G[u].size();i++)

        {

            v = G[u][i].first;

            w = G[u][i].second;

            if(dis[v] > dis[u] + w)

            {

                dis[v] = dis[u] + w;

                if(!inq[v])

                {

                    inq[v] = 1;

                    cnt[v]++;

                    if(cnt[v] >= n+1)

                        return false;

                    que.push(v);

                }

            }

        }

    }

    return true;

}



int main()

{

    int i,j;

    int L,R,A,B;

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        for(i=0;i<=n+3;i++)

            G[i].clear();

        while(m--)

        {

            scanf("%d%d%d%d",&L,&R,&A,&B);

            G[R].push_back(make_pair(L-1,-A));

            G[L-1].push_back(make_pair(R,B));

        }

        for(i=1;i<=n;i++)

        {

            G[i].push_back(make_pair(i-1,10000));

            G[i-1].push_back(make_pair(i,10000));

        }

        if(SPFA(0))

        {

            for(i=1;i<=n+1;i++)

            {

                if(dis[i] != Mod)

                    sum[i] = dis[i];

                else

                    sum[i] = sum[i-1];

            }

            printf("%d",sum[1]);

            for(i=2;i<=n;i++)

                printf(" %d",sum[i]-sum[i-1]);

            printf("\n");

        }

        else

            puts("The spacecraft is broken!");

    }

    return 0;

}
View Code

 

你可能感兴趣的:(super)