Schedule Problem spfa 差分约束

  

题意:有n个任务,给出完成n个任务所需时间,以及一些任务安排。任务安排有四种:

FAS a b:任务a需在任务b开始后完成。

FAF a b:任务a需在任务b完成后完成。

SAF a b:任务a需在任务b完成后开始。

SAS a b:任务a需在任务b开始后开始。

求在这些任务安排下各个任务的最早开始时间,若任务安排为不可能安排则输出impossible。每组数据结束需要输出一个空行。

思路:四种任务安排可以得到四种不等式如下:(dis[]表示任务开始时间,x[]表示任务完成所需时间)

FAS a b:dis[a]+x[a]>=dis[b]

FAF a b:dis[a]+x[a]>=dis[b]+x[b]

SAF a b:dis[a]>=dis[b]+x[b]

SAS a b:dis[a]>=dis[b]

因为求任务开始的最早时间即最小值,加上此题有好多的不等式可以进行差分约束。所以建图,spfa()最长路即可求得答案。

终于看到一个比较不那么抽象的差分约束了

记得连上超级源点0

显然不可能有短路

当有环的时候没有答案!

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f
#define N 100000
int head[N];
int pos;
struct node
{
    int to,v,nex;
}edge[10000000];
void add(int a,int b,int c)
{
    edge[++pos].nex=head[a];
    head[a]=pos;
    edge[pos].v=c;
    edge[pos].to=b;
}
int n;

int vis[N],dis[N],cnt[N];
bool spfa()
{
    rep(i,1,n)
    vis[i]=0,dis[i]=-inf,cnt[i]=0;
    dis[0]=0;
    vis[0]=1;
    cnt[0]++;
    queue<int>q;
    q.push(0);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        vis[u]=0;
        for(int i=head[u];i;i=edge[i].nex)
        {
            int v=edge[i].to;
            if(dis[v]<dis[u]+edge[i].v)
            {
                dis[v]=dis[u]+edge[i].v;
                if(!vis[v])
                {
                    if(++cnt[v]>n)return 0;
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return 1;
}
int t[N];
int main()
{
    int cas=0;
    while(RI(n),n)
    {
        printf("Case %d:\n",++cas);
        CLR(head,0);
        pos=0;
        rep(i,1,n)RI(t[i]);

        int a,b;
        char s[5];
        while(1)
        {
            RS(s);
            if(s[0]=='#')break;
            RII(a,b);
            if(s[0]=='F')
            {
                if(s[2]=='S')
                    add(b,a,-t[a]);
                else
                    add(b,a,t[b]-t[a]);
            }
            else
            {
                if(s[2]=='F')
                    add(b,a,t[b]);
                else
                    add(b,a,0);
            }
        }
        rep(i,1,n)
        add(0,i,0);
        
        if(spfa())
        {
            rep(i,1,n)
            printf("%d %d\n",i,dis[i]);
        }
        else
        printf("impossible\n");
        cout<<endl;
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/bxd123/p/10780752.html