HDU--1534(差分约束)
2015-01-08 01:06:22
思路:
这题有两种思路。
(1)第一种也是我一开始想的:拆点,将一个任务拆成开始的时间点和结束的时间点,让任务1拥有1,2点,任务2拥有3,4点,...以此类推第i个任务开始点:2*i-1,结束点:2*i
那么约束条件就变为:S(2*i) - S(2*i-1) >= t[i]
S(2*i) - S(2*i-1) <= t[i] (这样就保证了任务时长为t[i])
FAS: S(2*a) - S(2*b-1) >= 0
FAF: S(2*a) - S(2*b) >= 0
SAF: S(2*a-1) - S(2*b) >= 0
SAS: S(2*a-1) - S(2*b-1) >= 0
由于要求的是最小需要时间,所以建完这些边后加入一个超级源点,与所有点建边,权为0,跑一遍最长路即可。
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 typedef pair<int,int> pii; 20 const int INF = (1 << 30) - 1; 21 const int maxn = 20010; 22 23 int n,t[maxn]; 24 int first[maxn],ecnt; 25 int inq[maxn],cnt[maxn],dis[maxn]; 26 27 struct edge{ 28 int v,next,cost; 29 }e[maxn << 1]; 30 31 void Add_edge(int u,int v,int c){ 32 e[++ecnt].next = first[u]; 33 e[ecnt].v = v; 34 e[ecnt].cost = c; 35 first[u] = ecnt; 36 } 37 38 bool Spfa(int s){ 39 queue<int> Q; 40 memset(inq,0,sizeof(inq)); 41 memset(cnt,0,sizeof(cnt)); 42 fill(dis + 1,dis + 2 * n + 1,-INF); 43 dis[s] = 0; 44 cnt[s] = 1; 45 Q.push(s); 46 while(!Q.empty()){ 47 int x = Q.front(); Q.pop(); 48 inq[x] = 0; 49 for(int i = first[x]; i != -1; i = e[i].next){ 50 int v = e[i].v; 51 if(dis[v] < dis[x] + e[i].cost){ 52 dis[v] = dis[x] + e[i].cost; 53 if(inq[v] == 0){ 54 inq[v] = 1; 55 if(++cnt[v] > 2 * n + 1) return false; 56 Q.push(v); 57 } 58 } 59 } 60 } 61 return true; 62 } 63 64 int main(){ 65 char s[10]; 66 int a,b,Case = 0; 67 while(scanf("%d",&n) != EOF,n){ 68 memset(first,-1,sizeof(first)); 69 ecnt = 0; 70 for(int i = 1; i <= n; ++i){ 71 scanf("%d",&t[i]); 72 Add_edge(2 * i - 1,2 * i,t[i]); 73 Add_edge(2 * i,2 * i - 1,-t[i]); 74 } 75 while(scanf("%s",s) != EOF){ 76 if(s[0] == '#') break; 77 scanf("%d%d",&a,&b); 78 if(s[0] == 'F'){ 79 if(s[2] == 'S') Add_edge(2 * b - 1,2 * a,0); 80 else Add_edge(2 * b,2 * a,0); 81 } 82 else{ 83 if(s[2] == 'F') Add_edge(2 * b,2 * a - 1,0); 84 else Add_edge(2 * b - 1,2 * a - 1,0); 85 } 86 } 87 for(int i = 2 * n; i >= 1; --i) Add_edge(0,i,0); 88 printf("Case %d:\n",++Case); 89 if(Spfa(0) == false) printf("impossible\n"); 90 else{ 91 for(int i = 1; i <= n; ++i) 92 printf("%d %d\n",i,dis[2 * i - 1]); 93 } 94 puts(""); 95 } 96 return 0; 97 }
(2)第二种就比较正常一点了。 每个任务一个点,表示任务开始时间。当然超级源点也是要建的(不然就要把所有点先全部入队...也是一种写法)
FAS: S(a) + t[a] - S(b) >= 0
FAF: S(a) + t[a] - (S(b) + t[b]) >= 0
SAF: S(a) - (S(b) + t[b]) >= 0
SAS: S(a) - S(b) >= 0
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 typedef pair<int,int> pii; 20 const int INF = (1 << 30) - 1; 21 const int maxn = 20010; 22 23 int n,t[maxn]; 24 int first[maxn],ecnt; 25 int inq[maxn],cnt[maxn],dis[maxn]; 26 27 struct edge{ 28 int v,next,cost; 29 }e[maxn << 1]; 30 31 void Add_edge(int u,int v,int c){ 32 e[++ecnt].next = first[u]; 33 e[ecnt].v = v; 34 e[ecnt].cost = c; 35 first[u] = ecnt; 36 } 37 38 bool Spfa(int s){ 39 queue<int> Q; 40 memset(inq,0,sizeof(inq)); 41 memset(cnt,0,sizeof(cnt)); 42 fill(dis + 1,dis + n + 1,-INF); 43 dis[s] = 0; 44 cnt[s] = 1; 45 Q.push(s); 46 while(!Q.empty()){ 47 int x = Q.front(); Q.pop(); 48 inq[x] = 0; 49 for(int i = first[x]; i != -1; i = e[i].next){ 50 int v = e[i].v; 51 if(dis[v] < dis[x] + e[i].cost){ 52 dis[v] = dis[x] + e[i].cost; 53 if(inq[v] == 0){ 54 inq[v] = 1; 55 if(++cnt[v] > n + 1) return false; 56 Q.push(v); 57 } 58 } 59 } 60 } 61 return true; 62 } 63 64 int main(){ 65 char s[10]; 66 int a,b,Case = 0; 67 while(scanf("%d",&n) != EOF,n){ 68 memset(first,-1,sizeof(first)); 69 ecnt = 0; 70 for(int i = 1; i <= n; ++i) scanf("%d",t + i); 71 while(scanf("%s",s) != EOF && s[0] != '#'){ 72 scanf("%d%d",&a,&b); 73 if(s[0] == 'F'){ 74 if(s[2] == 'S') Add_edge(b,a,-t[a]); 75 else Add_edge(b,a,t[b] - t[a]); 76 } 77 else{ 78 if(s[2] == 'F') Add_edge(b,a,t[b]); 79 else Add_edge(b,a,0); 80 } 81 } 82 for(int i = 1; i <= n; ++i) Add_edge(0,i,0); 83 printf("Case %d:\n",++Case); 84 if(Spfa(0) == false) printf("impossible\n"); 85 else{ 86 for(int i = 1; i <= n; ++i) 87 printf("%d %d\n",i,dis[i]); 88 } 89 puts(""); 90 } 91 return 0; 92 }