码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4309 Seikimatsu Occult Tonneru (枚举+最大流)

时间:2014-08-24 01:31:52      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   for   ar   art   

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=4309

 

题意:

 

 

方法:

用二进制枚举所有p>0的边是否修,然后按下面建图,跑最大流,输出最大的最大流及其对应的修桥费用

建图:

对于每个城市顶点i,连边S->i,流量为城市的人数

如果p<0,连u->v,流量inf;u->T,流量w

如果p==0,连u->v,流量inf;

如果p>0,如果此桥被标记修,则连u->v,流量inf;否则连u->v,流量1;

 1 void solve()
 2 {
 3     for (int i = 0; i < (1 << rec.size()); i++)
 4     {
 5         tcost = 0;
 6         for (int j = 0; j < rec.size(); j++)
 7             if (i & (1 << j)) e[rec[j]].flag = 1, tcost += e[rec[j]].w;
 8         cal();
 9         for (int j = 0; j < rec.size(); j++)
10             if (i & (1 << j)) e[rec[j]].flag = 0;
11     }
12 }
 1 void build()
 2 {
 3     dinic.init(n + 2);
 4     dinic.st = 0;
 5     dinic.ed = 1;
 6     for (int i = 0; i < n; i++)
 7         dinic.adde(dinic.st, i + 2, a[i]);
 8     for (int i = 0; i < m; i++)
 9     {
10         int u = e[i].u;
11         int v = e[i].v;
12         int w = e[i].w;
13         int p = e[i].p;
14         if (p < 0)
15         {
16             dinic.adde(u + 2, v + 2, inf);
17             dinic.adde(u + 2, dinic.ed, w);
18         }
19         else if (p == 0) dinic.adde(u + 2, v + 2, inf);
20         else
21         {
22             if (e[i].flag) dinic.adde(u + 2, v + 2, inf);
23             else dinic.adde(u + 2, v + 2, 1);
24         }
25     }
26 }

 

代码:

bubuko.com,布布扣
  1 /*************************************
  2 *ACM Solutions
  3 *@Author: xysmlx
  4 *@Blog: http://www.cnblogs.com/xysmlx
  5 *************************************/
  6 // #pragma comment(linker, "/STACK:102400000,102400000")
  7 #include <cstdio>
  8 #include <iostream>
  9 #include <cstring>
 10 #include <string>
 11 #include <cmath>
 12 #include <set>
 13 #include <list>
 14 #include <map>
 15 #include <iterator>
 16 #include <cstdlib>
 17 #include <vector>
 18 #include <queue>
 19 #include <stack>
 20 #include <algorithm>
 21 #include <functional>
 22 using namespace std;
 23 typedef long long LL;
 24 #define pb push_back
 25 #define ROUND(x) round(x)
 26 #define FLOOR(x) floor(x)
 27 #define CEIL(x) ceil(x)
 28 // const int maxn = 0;
 29 // const int maxm = 0;
 30 // const int inf = 0x3f3f3f3f;
 31 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL;
 32 const double INF = 1e30;
 33 const double eps = 1e-6;
 34 const int P[4] = {0, 0, -1, 1};
 35 const int Q[4] = {1, -1, 0, 0};
 36 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1};
 37 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1};
 38 
 39 /**
 40 *最大流最小割:加各种优化的Dinic算法($O(V^2E)$)
 41 *输入:图(链式前向星),n(顶点个数,包含源汇),st(源),ed(汇)
 42 *输出:Dinic(NdFlow)(最大流),MinCut()(最小割)(需先求最大流)
 43 *打印路径方法:按反向边(i&1)的flow 找,或者按边的flow找
 44 */
 45 const int maxn = 510;
 46 const int maxm = 20010;
 47 const int inf = 0x3f3f3f3f;
 48 struct DINIC
 49 {
 50     struct Edge
 51     {
 52         int u, v;
 53         int cap, flow;
 54         int next;
 55     } edge[maxm];
 56     int head[maxn], en; //需初始化
 57     int n, m, d[maxn], cur[maxn];
 58     int st, ed;
 59     bool vis[maxn];
 60     void init(int _n = 0)
 61     {
 62         n = _n;
 63         memset(head, -1, sizeof(head));
 64         en = 0;
 65     }
 66     void addse(int u, int v, int cap, int flow)
 67     {
 68         edge[en].u = u;
 69         edge[en].v = v;
 70         edge[en].cap = cap;
 71         edge[en].flow = flow;
 72         edge[en].next = head[u];
 73         head[u] = en++;
 74         cur[u] = head[u];
 75     }
 76     void adde(int u, int v, int cap)
 77     {
 78         addse(u, v, cap, 0);
 79         addse(v, u, 0, 0); //注意加反向0 边
 80     }
 81     bool BFS()
 82     {
 83         queue<int> Q;
 84         memset(vis, 0, sizeof(vis));
 85         Q.push(st);
 86         d[st] = 0;
 87         vis[st] = 1;
 88         while (!Q.empty())
 89         {
 90             int u = Q.front();
 91             Q.pop();
 92             for (int i = head[u]; i != -1; i = edge[i].next)
 93             {
 94                 int v = edge[i].v;
 95                 int w = edge[i].cap - edge[i].flow;
 96                 if (w > 0 && !vis[v])
 97                 {
 98                     vis[v] = 1;
 99                     Q.push(v);
100                     d[v] = d[u] + 1;
101                     if (v == ed) return 1;
102                 }
103             }
104         }
105         return false;
106     }
107     int Aug(int u, int a)
108     {
109         if (u == ed) return a;
110         int aug = 0, delta;
111         for (int &i = cur[u]; i != -1; i = edge[i].next)
112         {
113             int v = edge[i].v;
114             int w = edge[i].cap - edge[i].flow;
115             if (w > 0 && d[v] == d[u] + 1)
116             {
117                 delta = Aug(v, min(a, w));
118                 if (delta)
119                 {
120                     edge[i].flow += delta;
121                     edge[i ^ 1].flow -= delta;
122                     aug += delta;
123                     if (!(a -= delta)) break;
124                 }
125             }
126         }
127         if (!aug) d[u] = -1;
128         return aug;
129     }
130     int Dinic(int NdFlow)
131     {
132         int flow = 0;
133         while (BFS())
134         {
135             memcpy(cur, head, sizeof(int) * (n + 1));
136             flow += Aug(st, inf);
137             /*如果超过指定流量就return 掉*/
138             if (NdFlow == inf) continue;
139             if (flow > NdFlow) break;
140         }
141         return flow;
142     }
143     /*残余网络*/
144     void Reduce()
145     {
146         for (int i = 0; i < en; i++) edge[i].cap -= edge[i].flow;
147     }
148     /*清空流量*/
149     void ClearFlow()
150     {
151         for (int i = 0; i < en; i++) edge[i].flow = 0;
152     }
153     /*求最小割*/
154     vector<int> MinCut()
155     {
156         BFS();
157         vector<int> ans;
158         for (int u = 0; u < n; u++)
159         {
160             if (!vis[u]) continue;
161             for (int i = head[u]; i != -1; i = edge[i].next)
162             {
163                 if (i & 1) continue; /*忽略反向边*/
164                 int v = edge[i].v;
165                 int w = edge[i].cap;
166                 if (!vis[v] && w > 0) ans.push_back(i);
167             }
168         }
169         return ans;
170     }
171 } dinic;
172 
173 int kase;
174 int n, m;
175 int a[maxn];
176 int cost;
177 int flow;
178 int tcost;
179 struct Edge
180 {
181     int u, v;
182     int w;
183     int p;
184     int flag;
185     Edge(int _u, int _v, int _w, int _p): u(_u), v(_v), w(_w), p(_p) {}
186     Edge() {}
187 };
188 vector<Edge> e;
189 vector<int> rec;
190 void init()
191 {
192     kase++;
193     e.clear();
194     rec.clear();
195     flow = 0;
196     cost = inf;
197 }
198 void input()
199 {
200     for (int i = 0; i < n; i++)
201         scanf("%d", &a[i]);
202     for (int i = 0; i < m; i++)
203     {
204         int u, v, w, p;
205         scanf("%d%d%d%d", &u, &v, &w, &p);
206         u--, v--;
207         e.pb(Edge(u, v, w, p));
208         e[i].flag = 0;
209         if (p > 0) rec.pb(i);
210     }
211 }
212 void debug()
213 {
214     //
215 }
216 void build()
217 {
218     dinic.init(n + 2);
219     dinic.st = 0;
220     dinic.ed = 1;
221     for (int i = 0; i < n; i++)
222         dinic.adde(dinic.st, i + 2, a[i]);
223     for (int i = 0; i < m; i++)
224     {
225         int u = e[i].u;
226         int v = e[i].v;
227         int w = e[i].w;
228         int p = e[i].p;
229         if (p < 0)
230         {
231             dinic.adde(u + 2, v + 2, inf);
232             dinic.adde(u + 2, dinic.ed, w);
233         }
234         else if (p == 0) dinic.adde(u + 2, v + 2, inf);
235         else
236         {
237             if (e[i].flag) dinic.adde(u + 2, v + 2, inf);
238             else dinic.adde(u + 2, v + 2, 1);
239         }
240     }
241 }
242 void cal()
243 {
244     build();
245     int tmp = dinic.Dinic(inf);
246     if (tmp > flow)
247     {
248         flow = tmp;
249         cost = tcost;
250     }
251 }
252 void solve()
253 {
254     for (int i = 0; i < (1 << rec.size()); i++)
255     {
256         tcost = 0;
257         for (int j = 0; j < rec.size(); j++)
258             if (i & (1 << j)) e[rec[j]].flag = 1, tcost += e[rec[j]].w;
259         cal();
260         for (int j = 0; j < rec.size(); j++)
261             if (i & (1 << j)) e[rec[j]].flag = 0;
262     }
263 }
264 void output()
265 {
266     cost = cost == inf ? 0 : cost;
267     if (flow == 0) puts("Poor Heaven Empire");
268     else printf("%d %d\n", flow, cost);
269 }
270 int main()
271 {
272     // int size = 256 << 20; // 256MB
273     // char *p = (char *)malloc(size) + size;
274     // __asm__("movl %0, %%esp\n" :: "r"(p));
275 
276     // std::ios_base::sync_with_stdio(false);
277 #ifdef xysmlx
278     freopen("in.cpp", "r", stdin);
279 #endif
280 
281     kase = 0;
282     while (~scanf("%d%d", &n, &m))
283     {
284         init();
285         input();
286         solve();
287         output();
288     }
289     return 0;
290 }
HDU 4309

 

HDU 4309 Seikimatsu Occult Tonneru (枚举+最大流)

标签:style   blog   http   color   os   io   for   ar   art   

原文地址:http://www.cnblogs.com/xysmlx/p/3932138.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!