HDOJ-1534(差分约束)

来源:互联网 发布:尼康全站仪导入数据 编辑:程序博客网 时间:2024/04/29 03:28

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1534

刚开始以为是AOE网络,将每个活动分解成开始点和结束点,感觉只要找到每个任务的最早结束时间,减去活动耗时就是可行的开始时间了,构图之后理论上所有点应该满足一个时间先后的顺序,拓扑排序的过程就行了,没想到WA了,大为不解,为什么不可以。。。

好吧,以差分约束的方式分析(差分约束之后解是唯一的,为什么题目还说是special judge呢):

先回忆一下,差分约束系统是用最短路模型解决的一类问题,针对形如x - y <= c的不等式组,物理含义上可以理解为,从起点到a点的最短路长度x <= 从起点到b点的最短路长度y +  常数c,所以构图时从b点向a点引一条长度为c的有向边。

对于本题,令每个活动的耗时为cost[i]、最早开始时间为dis[i](开始干活之前时间是0),则四种关系分别是:

(1)SAS x y:即x在y开始之后开始,则dis[x] >= dis[y],即dis[y] - dis[x] <= 0 <=> x到y有一条长度为0的有向边;

(2)SAF x y:即x在y完成之后开始,则dis[x] >= dis[y] + cost[y],即dis[y] - dis[x] <= -cost[y]  <=> x到y有一条长度为-cost[y]的有向边;

(3)FAS x y:即x在y开始之后完成,则dis[x] + cost[x] >= dis[y],即dis[y] - dis[x] <= cost[x] <=> x到y有一条长度为cost[x]的有向边;

(4)FAF x y:即x在y完成之后完成,则dis[x] + cost[x] >= dis[y] + cost[y],即dis[y] - dis[x] <= cost[x] - cost[y] <=> x到y有一条长度为cost[x]-cost[y]的有向边。

这样构图之后还要加一个超级源点作为起点,另外需要注意的是,最早开始的活动应该输出开始时间为0,因此我们在求出dis[]之后,要将所有的dis[i]减去min{dis[]}进行输出。


#include <cstdio>#include <cstring>#include <utility>#include <queue>#include <vector>#include <algorithm>using namespace std;#define MAX5005typedef pair<int,int> PII;int N, cost[MAX], dis[MAX], inq[MAX];vector<PII> vertex[MAX];bool vis[MAX];queue<int> Q;bool spfa(){while(!Q.empty()) Q.pop();memset(vis + 1, 0x00, N);memset(dis + 1, 0x7F, N << 2);memset(inq + 1, 0x00, N << 2);inq[0] = dis[0] = 0;Q.push(0); vis[0] = true;while(!Q.empty()){int x = Q.front(); Q.pop(); vis[x] = false;vector<PII>& v = vertex[x];for(int i = v.size() - 1; i > -1; --i){int y = v[i].first, d = v[i].second;if(dis[y] > dis[x] + d){dis[y] =  dis[x] + d;if(!vis[y]){Q.push(y);vis[y] = true;if(++inq[y] > N) return false;}}}}return true;}int main(){int kase = 0, i, x, y, d;char s[4];while(++kase, scanf("%d", &N), N){//initfor(i = 0; i <= N; ++i) vertex[i].clear();//inputfor(i = 1; i <= N; ++i)scanf("%d", cost + i);while(scanf("%s", s), s[0] != '#'){scanf("%d%d", &x, &y);if(s[0] == 'S'){if(s[2] == 'S') d = 0;else d = -cost[y];}else{if(s[2] == 'S') d = cost[x];else d = cost[x] - cost[y];}vertex[x].push_back(PII(y, d));}//add super sourcefor(i = 1; i <= N; ++i) vertex[0].push_back(PII(i, 0));//figure out disif(spfa()){d = *min_element(dis + 1, dis + N + 1);printf("Case %d:\n", kase);for(i = 1; i <= N; ++i) printf("%d %d\n", i, dis[i] - d);puts("");}else printf("Case %d:\nimpossible\n\n", kase);}return 0;}


0 0