标签:
Asia 1996, Shanghai (Mainland China)
题目大意:安排N个工作 ,给你N个工作的开始时间,共有4种安排方式(约束条件)。
条件1:FAF a b,a要在b完成后完成。
条件2:FAS a b,a在在b开始前完成。
条件3:SAS a b,a要在b开始前开始。
条件4:SAF a b,a要在b结束前开始。
给你一系列的约束条件。问:使其工作时间最小且满足所有约束条件的各个工作最早
时间各是什么。如果不满足条件则输出"impossible"。
思路:差分约束系统。设第i件工作的开始时间为t[i]。4个约束条件变成:
条件1:FAF Sa + t[a] - (Sb + t[b]) >= 0
条件2:FAS Sa + t[a] - Sb >= 0
条件3:SAS Sa - Sb >= 0
条件4:SAF Sa - (Sb + t[b]) >= 0
转换为差分约束系统:
条件1:FAF Sb - Sa <= t[a]-t[b]
条件2:FAS Sb - Sa <= t[a]
条件3:SAS Sb - Sa <= 0
条件4:SAF Sb - Sa <= -t[b]
最后求出的Dist[]数组即为各项工作开始的最早时间。不过题目要求最早开始时间为0。
所以计算出Dist[]数组中最小的项,每项工作开始的最早时间减去最小的项即为答案。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = 1010;
const int MAXM = MAXN*MAXN;
const int INF = 0xffffff0;
struct EdgeNode
{
int to;
int w;
int next;
}Edges[MAXM];
int id,Head[MAXN],Dist[MAXN],vis[MAXN],outque[MAXN],num[MAXN];
void AddEdges(int u,int v,int w)
{
Edges[id].to = v;
Edges[id].w = w;
Edges[id].next = Head[u];
Head[u] = id++;
}
bool SPFA(int s,int N)
{
memset(vis,0,sizeof(vis));
memset(outque,0,sizeof(outque));
for(int i = 0; i <= N; ++i)
Dist[i] = INF;
queue<int> Q;
Dist[s] = 0;
vis[s] = 1;
Q.push(s);
while( !Q.empty() )
{
int u = Q.front();
Q.pop();
vis[u] = 0;
outque[u]++;
if(outque[u] > N)
return false;
for(int i = Head[u]; i != -1; i = Edges[i].next)
{
int temp = Dist[u] + Edges[i].w;
if(temp < Dist[Edges[i].to])
{
Dist[Edges[i].to] = temp;
if( !vis[Edges[i].to])
{
vis[Edges[i].to] = 1;
Q.push(Edges[i].to);
}
}
}
}
return true;
}
int main()
{
int N,kase = 0,u,v;
char ch[4];
while(~scanf("%d",&N) && N)
{
int Min = INF;
for(int i = 1; i <= N; ++i)
scanf("%d", &num[i]);
memset(Head,-1,sizeof(Head));
id = 0;
while(scanf("%s",ch) && ch[0] != '#')
{
scanf("%d%d", &u, &v);
if(strcmp(ch,"SAS") == 0)
AddEdges(u,v,0);
else if(strcmp(ch,"SAF") == 0)
AddEdges(u,v,-num[v]);
else if(strcmp(ch,"FAS") == 0)
AddEdges(u,v,num[u]);
else
AddEdges(u,v,num[u]-num[v]);
}
for(int i = 1; i <= N; ++i)
AddEdges(0,i,0);
printf("Case %d:\n",++kase);
if(SPFA(0,N) == 0)
{
printf("impossible\n\n");
continue;
}
for(int i = 1; i <= N; ++i)
if(Dist[i] < Min)
Min = Dist[i];
for(int i = 1; i <= N; ++i)
printf("%d %d\n", i, Dist[i]-Min);
printf("\n");
}
return 0;
}
HDU1534 Schedule Problem【SPFA】【差分约束】
标签:
原文地址:http://blog.csdn.net/lianai911/article/details/43193179