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;
}