首页 > 代码库 > HDU 4309 Seikimatsu Occult Tonneru (枚举+最大流)
HDU 4309 Seikimatsu Occult Tonneru (枚举+最大流)
题目:
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 else21 {22 if (e[i].flag) dinic.adde(u + 2, v + 2, inf);23 else dinic.adde(u + 2, v + 2, 1);24 }25 }26 }
代码:
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 Edge180 {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 else236 {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; // 256MB273 // 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 xysmlx278 freopen("in.cpp", "r", stdin);279 #endif280 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 Seikimatsu Occult Tonneru (枚举+最大流)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。