题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1534
题意:
有n个作业,第 i 个作业所需的时间是 time[i],第i个作业开始的时间为d[i],时间从0开始。求满足这些约束条件时,花费时间最小的情况时,每一个作业的开始时间。
四种约束条件如下:
SAS u v 表示 v开始后 u 才能开始;d(u)>=d(v);
SAF u v 表示 v结束后 u 才能开始;d(u)>=d(v)+time[v];
FAF u v 表示 v结束后 u 才能结束;d(u)+time[u]>=d(v)+time[v];
FAS u v 表示 v开始后 u 才能结束;d(u)+time[u]>=d(v);
分析:求最小时间,就是差分约束跑最长路即可。
代码:
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <queue>
using namespace std;
const int maxn =100000+5;
const int inf =0x3f3f3f3f;
int head[maxn],d[maxn],vis[maxn],cnt,N,num[maxn],time[maxn],flag[maxn],k=1;
queue<int> q;
void init()
{
cnt=0;
memset(flag,0,sizeof(flag));
memset(head,-1,sizeof(head));
memset(d,0,sizeof(d));
while(!q.empty())
q.pop();
}
struct Edge
{
int v,w,next;
Edge() {};
Edge(int _v, int _w, int _next)
{
v=_v, w=_w, next=_next;
}
} e[20*maxn];
void add_edge(int u, int v, int w)
{
e[cnt]=Edge(v,w,head[u]);
head[u]=cnt++;
}
int spfa(int s)
{
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(num));
d[s]=0;
q.push(s);
vis[s]=1;
num[s]++;
while(!q.empty())
{
int u= q.front();
q.pop();
vis[u]=0;
flag[u]=1;
for(int i=head[u]; i!=-1; i=e[i].next)
{
int v=e[i].v;
if(d[v]<d[u]+e[i].w)
{
d[v]=d[u]+e[i].w;
if(!vis[v])
{
q.push(v);
vis[v]=1;
num[v]++;
if(num[v]>N)
return 0;
}
}
}
}
return 1;
}
int main()
{
while(cin>>N&&N)
{
init();
for(int i=1; i<=N; i++)
cin>>time[i];
string str;
int a,b;
while(cin>>str&&str!="#")
{
cin>>a>>b;
if(str=="SAS")
{
add_edge(b,a,0);
}
else if(str=="SAF")
{
add_edge(b,a,time[b]);
}
else if(str=="FAF")
{
add_edge(b,a,time[b]-time[a]);
}
else if(str=="FAS")
{
add_edge(b,a,-time[a]);
}
}
cout<<"Case "<<k++<<":"<<endl;
int yes;
for(int i=1; i<=N; i++)
{
if(!flag[i])
{
yes=spfa(i);
}
if(yes==0)
break;
}
if(yes)
{
for(int i=1; i<=N; i++)
{
cout<<i<<" "<<d[i]<<endl;
}
}
else
{
cout<<"impossible"<<endl;
}
cout<<endl;
}
return 0;
}