POJ 1275 Cashier Employment(差分约束)
详情请看黑书第306页。。。完全根据书做的,我把s[-1]改为s[24]了。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <string> 5 #include <ctime> 6 #include <queue> 7 #include <vector> 8 using namespace std; 9 #define INF 10000000 10 struct node 11 { 12 int u,v,w,next; 13 }edge[100*100]; 14 int first[101],in[101],dis[101],num[101]; 15 int t; 16 int s[31],r[31],ti[31]; 17 void CL() 18 { 19 t = 1; 20 memset(first,-1,sizeof(first)); 21 } 22 void add(int u,int v,int w) 23 { 24 edge[t].u = u; 25 edge[t].v = v; 26 edge[t].w = w; 27 edge[t].next = first[u]; 28 first[u] = t ++; 29 } 30 int spfa() 31 { 32 int i,u,v; 33 for(i = 0;i <= 24;i ++) 34 { 35 dis[i] = -INF; 36 in[i] = 0; 37 num[i] = 0; 38 } 39 queue<int> que; 40 que.push(24); 41 in[24] = 1; 42 dis[24] = 0; 43 num[24] = 1; 44 while(!que.empty()) 45 { 46 u = que.front(); 47 in[u] = 0; 48 que.pop(); 49 for(i = first[u];i != -1;i = edge[i].next) 50 { 51 v = edge[i].v; 52 if(dis[v] < dis[u] + edge[i].w) 53 { 54 dis[v] = dis[u] + edge[i].w; 55 if(!in[v]) 56 { 57 in[v] = 1; 58 que.push(v); 59 num[v] ++; 60 if(num[v] > 24) 61 return 1; 62 } 63 } 64 } 65 } 66 return 0; 67 } 68 int judge(int mid) 69 { 70 CL(); 71 int i,j; 72 for(i = 1;i <= 23;i ++) 73 { 74 add(i-1,i,0); 75 add(i,i-1,-ti[i]); 76 } 77 add(24,0,0); 78 add(0,24,-ti[0]); 79 add(24,23,mid); 80 for(j = 0;j <= 23;j ++) 81 { 82 i = (j + 8)%24; 83 if(i > j) 84 add(j,i,r[i]); 85 else 86 add(j,i,r[i]-mid); 87 } 88 if(!spfa()&&dis[23] == mid) 89 return 1; 90 else 91 return 0; 92 } 93 int main() 94 { 95 int i,j,cas,n,maxz; 96 scanf("%d",&cas); 97 while(cas --) 98 { 99 maxz = 0; 100 for(i = 0;i < 24;i ++) 101 { 102 scanf("%d",&r[i]); 103 if(maxz < r[i]) 104 maxz = r[i]; 105 } 106 scanf("%d",&n); 107 for(i = 0;i < n;i ++) 108 { 109 scanf("%d",&j); 110 ti[j] ++; 111 } 112 for(i = 0;i <= n;i ++) 113 { 114 if(judge(i)) 115 { 116 printf("%d\n",i); 117 break; 118 } 119 } 120 if(i == n+1) 121 printf("No Solution\n"); 122 } 123 return 0; 124 }