题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4494
【题意】有N个城市(坐标Xi,Yi)需要修复,m种兵种,修复有开始时间和完成时间,对每种兵种有人数要求。初始兵种都在X0,Y0位置。两个城市之间转移士兵需要的时间是欧几里得距离。求休整完所有城市,最少需要多少士兵。
【分析】
1、对于每个兵种相互独立没有影响,因此,对于每种兵种求出最小值求和。
2、对于每个任务建图,有两种做法,一种是跑费用流;一种是跑可行流判定。
费用流:每个点拆为3个点,x,y,z,(s,x,inf,0),(x,y,t,need,0),(x,y,need,0),(s,z,need,0);对于i != k如果ed[i] + dis(i,j) <= st[j],(iz,ky,ineed,0);求最小费用即可。
这里添加点z,表示,i点的流量ineed可以跑到k点,继续使用,费用为0。
这个模板很好用。


1 #include<functional> 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 #define REP(i, n) for(int i=0; i<n; i++) 10 #define FF(i, a, b) for(int i=a; i<b; i++) 11 #define CLR(a, b) memset(a, b, sizeof(a)) 12 #define PB push_back 13 using namespace std; 14 15 const int MAXN = 455; 16 const int MAXE = MAXN*MAXN/2; 17 const int INF = 1e9; 18 struct ZKW_flow 19 { 20 int st, ed, ecnt, n; 21 int head[MAXN]; 22 int cap[MAXE], cost[MAXE], to[MAXE], next[MAXE], dis[MAXN]; ; 23 24 void init() 25 { 26 memset(head, 0, sizeof(head)); 27 ecnt = 2; 28 } 29 30 void AddEdge(int u, int v, int cc, int ww) 31 { 32 cap[ecnt] = cc; 33 cost[ecnt] = ww; 34 to[ecnt] = v; 35 next[ecnt] = head[u]; 36 head[u] = ecnt++; 37 cap[ecnt] = 0; 38 cost[ecnt] = -ww; 39 to[ecnt] = u; 40 next[ecnt] = head[v]; 41 head[v] = ecnt++; 42 } 43 44 void SPFA() 45 { 46 REP(i, n+1) dis[i] = INF; 47 priority_queue<pair<int, int> > Q; 48 dis[st] = 0; 49 Q.push(make_pair(0, st)); 50 while(!Q.empty()) 51 { 52 int u = Q.top().second, d = -Q.top().first; 53 Q.pop(); 54 if(dis[u] != d) continue; 55 for(int p = head[u]; p; p = next[p]) 56 { 57 int &v = to[p]; 58 if(cap[p] && dis[v] > d + cost[p]) 59 { 60 dis[v] = d + cost[p]; 61 Q.push(make_pair(-dis[v], v)); 62 } 63 } 64 } 65 REP(i, n+1) dis[i] = dis[ed] - dis[i]; 66 } 67 68 int minCost, maxFlow; 69 bool use[MAXN]; 70 71 int add_flow(int u, int flow) 72 { 73 if(u == ed) 74 { 75 maxFlow += flow; 76 minCost += dis[st] * flow; 77 return flow; 78 } 79 use[u] = true; 80 int now = flow; 81 for(int p = head[u]; p; p = next[p]) 82 { 83 int &v = to[p]; 84 if(cap[p] && !use[v] && dis[u] == dis[v] + cost[p]) 85 { 86 int tmp = add_flow(v, min(now, cap[p])); 87 cap[p] -= tmp; 88 cap[p^1] += tmp; 89 now -= tmp; 90 if(!now) break; 91 } 92 } 93 return flow - now; 94 } 95 96 bool modify_label() 97 { 98 int d = INF; 99 REP(u, n+1) if(use[u]) 100 for(int p = head[u]; p; p = next[p]) 101 { 102 int &v = to[p]; 103 if(cap[p] && !use[v]) d = min(d, dis[v] + cost[p] - dis[u]); 104 } 105 if(d == INF) return false; 106 REP(i, n+1) if(use[i]) dis[i] += d; 107 return true; 108 } 109 110 int Mincost(int ss, int tt, int nn) 111 { 112 st = ss, ed = tt, n = nn; 113 minCost = maxFlow = 0; 114 SPFA(); 115 while(true) 116 { 117 while(true) 118 { 119 CLR(use, 0); 120 if(!add_flow(st, INF)) break; 121 } 122 if(!modify_label()) break; 123 } 124 return minCost; 125 } 126 } Flow; 127 128 int n, m; 129 130 struct Point{ 131 double x, y; 132 double st, ed; 133 int v[11]; 134 135 }sq[111]; 136 137 double dist(Point p, Point q) 138 { 139 return sqrt((p.x - q.x)*(p.x - q.x) + (p.y - q.y)*(p.y - q.y)); 140 } 141 142 void solve() 143 { 144 int s = 0, t = 3*n + 1; 145 int res = 0; 146 for (int j=0;j<m;j++) 147 { 148 Flow.init(); 149 for (int i=1;i<n;i++) 150 { 151 Flow.AddEdge(s, i,INF, 1); 152 Flow.AddEdge(i,i+2*n,sq[i].v[j],0); 153 Flow.AddEdge(i+2*n, t, sq[i].v[j],0); 154 Flow.AddEdge(s, i+n, sq[i].v[j], 0); 155 } 156 for (int i=1;i<n;i++) 157 { 158 for (int k=1;k<n;k++) 159 { 160 if (i != k) 161 { 162 if (sq[i].ed + dist(sq[i], sq[k]) <= sq[k].st) 163 { 164 Flow.AddEdge(i+n, k+2*n,sq[i].v[j],0); 165 } 166 } 167 } 168 } 169 res += Flow.Mincost(s,t,t); 170 } 171 printf("%d\n",res); 172 return ; 173 } 174 int main() 175 { 176 int cas; 177 scanf("%d", &cas); 178 while (cas--) 179 { 180 scanf("%d%d",&n,&m); 181 scanf("%lf%lf",&sq[0].x, &sq[0].y); 182 for (int i=1;i<n;i++) 183 { 184 scanf("%lf%lf%lf%lf",&sq[i].x, &sq[i].y, &sq[i].st, &sq[i].ed); 185 sq[i].ed += sq[i].st; 186 187 for (int j=0;j<m;j++) 188 { 189 scanf("%d",&sq[i].v[j]); 190 } 191 } 192 193 solve(); 194 } 195 return 0; 196 }