题意:有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: ",++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 ",i,dis[i]); } else printf("impossible "); cout<<endl; } return 0; }