HDU 1534 Schedule Problem(差分约束系统)
http://acm.hdu.edu.cn/showproblem.php?pid=1534
题意:有一个工程,它由N个部分构成,这N个部分都有一个连续的运行时间D[i]值,表示每一部分需要运行D[i]时间.现在的问题是,有M条约束条件需要满足,如FAS, FAF, SAF and SAS. FAS u v表示u部分的结束时间需要在v部分的开始时间之后.
问你该系统是否有解,如果有解的话,输出各个部分开始的时间.
分析:
我们令S[i]表示第i部分的开始时间,D[i]表示i部分运行的持续时间.
FAS u v 对应S[u]+D[u]>= S[v] 推出u到v的权值为D[u]的边
FAF u v 对应 S[u]+D[u]>=S[v]+D[v] 推出 u到v权值为D[u]-D[v]的边
SAF u v 对应 S[u]>=S[v]+D[v] 推出 u到v权值为-D[v]的边
SAS u v 对应 S[u]>=S[v] 推出u到v权值为0的边
构建有向图,由于该题可能无解,所以我们需要用超级源0号点去连接1到n号点.然后用BellmanFord算法判断是否有解.(用的是POJ1201提到的方案1)
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define INF 1E9
using namespace std;
const int maxn=10000+10;
const int maxm=200000+10;
struct Edge
{
int from,to,dist;
Edge(){}
Edge(int f,int t,int d):from(f),to(t),dist(d){}
};
struct BellmanFord
{
int n,m;
int head[maxn],next[maxm];
Edge edges[maxm];
int d[maxn];
bool inq[maxn];
int cnt[maxn];
void init(int n)
{
this->n=n;
m=0;
memset(head,-1,sizeof(head));
}
void AddEdge(int from,int to,int dist)
{
edges[m]=Edge(from,to,dist);
next[m]=head[from];
head[from]=m++;
}
bool bellmanford()
{
memset(inq,0,sizeof(inq));
memset(cnt,0,sizeof(cnt));
for(int i=0;i<n;i++) d[i]= i==0?0:INF;
queue<int> Q;
Q.push(0);
while(!Q.empty())
{
int u=Q.front(); Q.pop();
inq[u]=false;
for(int i=head[u];i!=-1;i=next[i])
{
Edge &e=edges[i];
if(d[e.to] > d[u]+e.dist)
{
d[e.to] = d[u]+e.dist;
if(!inq[e.to])
{
inq[e.to]=true;
Q.push(e.to);
if(++cnt[e.to]>n) return true;
}
}
}
}
return false;
}
}BF;
int D[maxn];//任务持续时间
int main()
{
int n,kase=0;
while(scanf("%d",&n)==1&&n)
{
if(kase>0) printf("\n");
printf("Case %d:\n",++kase);
BF.init(n+1);
for(int i=1;i<=n;i++)
scanf("%d",&D[i]);
char s[100];
int u,v;
while(scanf("%s",s)==1&&s[0]!='#')
{
scanf("%d%d",&u,&v);
if(strcmp(s,"FAS")==0)
BF.AddEdge(u,v,D[u]);
else if(strcmp(s,"FAF")==0)
BF.AddEdge(u,v,D[u]-D[v]);
else if(strcmp(s,"SAF")==0)
BF.AddEdge(u,v,-D[v]);
else if(strcmp(s,"SAS")==0)
BF.AddEdge(u,v,0);
}
for(int i=1;i<=n;i++)
BF.AddEdge(0,i,0);
if(BF.bellmanford()) printf("impossible\n");
else
{
int min_v=0;
for(int i=1;i<=n;i++)
min_v=min(min_v,BF.d[i]);
for(int i=1;i<=n;i++)
printf("%d %d\n",i,BF.d[i]-min_v);//保证最小时间>=0
}
}
return 0;
}