http://acm.hdu.edu.cn/showproblem.php?pid=1534
题目大意:
一个任务可以被划分为n个小的任务,每个小任务的时间是t[i],然后把这些小任务给员工们做。但是有的任务要建立在别的任务完成的情况下。
下面给出四种约束:FAS(a,b),FAF(a,b),SAS(a,b),SAF(a,b),以SAF为例,即a要在b结束之后开始。
求完成所有任务的最短时间
思路:
差分约束。。
最短时间就是求最小值也就是求最大路径。
FAS:a+t[a]>=b ---------> a-b>=-t[a];
FAF: a+t[a]>=b+t[b] ---------> a-b>=t[b]-t[a];
SAF: a>=b+t[b] ---------> a-b>=t[b]
SAS:a>=b ---------> a-b>=0
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; const int MAXN=10000+10; const int MAXM=200000; int head[MAXN],len,n,ml,md; int dis[MAXN],cnt[MAXN],t[MAXN]; bool vis[MAXN]; struct edge { int to,val,next; }e[MAXM]; void add(int from,int to,int val) { e[len].to=to; e[len].val=val; e[len].next=head[from]; head[from]=len++; } bool spfa() { queue<int> q; for(int i=1;i<=n;i++) { dis[i]=0; vis[i]=1; cnt[i]=1; q.push(i); } while(!q.empty()) { int cur=q.front(); q.pop(); vis[cur]=false; for(int i=head[cur];i!=-1;i=e[i].next) { int id=e[i].to; if(e[i].val + dis[cur] > dis[id]) { dis[id]=e[i].val + dis[cur]; if(!vis[id]) { if(++cnt[id]>n) return false; vis[id]=true; q.push(id); } } } } return true; } int main() { int kase=1; while(scanf("%d",&n),n) { memset(head,-1,sizeof(head)); len=0; for(int i=1;i<=n;i++) scanf("%d",&t[i]); char cmd[10]; while(scanf("%s",cmd),cmd[0]!='#') { int a,b; scanf("%d%d",&a,&b); if(strcmp("FAS",cmd)==0) add(b,a,-t[a]); else if(strcmp("FAF",cmd)==0) add(b,a,t[b]-t[a]); else if(strcmp("SAF",cmd)==0) add(b,a,t[b]); else if(strcmp("SAS",cmd)==0) add(b,a,0); } if(kase!=1) printf("\n"); printf("Case %d:\n",kase++); if(!spfa()) puts("impossible"); else { for(int i=1;i<=n;i++) printf("%d %d\n",i,dis[i]); } } return 0; }