poj 2987 最大权闭合图 最大流最小割模板
2015-08-13 10:11
447 查看
题意:
有一公司,公司里每个人都有自己的贡献值和自己的下属,下属也有下属。
现在要裁员,每裁掉一个人,他的下属也要被裁掉,下属的下属依次类推也要裁掉。
现在问,最小的裁员量和裁员完了以后最大的贡献值。
解析:
http://www.hankcs.com/program/algorithm/poj-2987-firing.html
最大权闭合图。
主要学习这种建图的抽象思维。
------------------------------->
发现原来的dinic模板算残量的时候有问题,EK的话MLE,加边还是MLE。
代码:
有一公司,公司里每个人都有自己的贡献值和自己的下属,下属也有下属。
现在要裁员,每裁掉一个人,他的下属也要被裁掉,下属的下属依次类推也要裁掉。
现在问,最小的裁员量和裁员完了以后最大的贡献值。
解析:
http://www.hankcs.com/program/algorithm/poj-2987-firing.html
最大权闭合图。
主要学习这种建图的抽象思维。
------------------------------->
发现原来的dinic模板算残量的时候有问题,EK的话MLE,加边还是MLE。
代码:
#pragma comment(linker, "/STACK:1677721600") #include <map> #include <set> #include <cmath> #include <queue> #include <stack> #include <vector> #include <cstdio> #include <cstdlib> #include <cstring> #include <climits> #include <cassert> #include <iostream> #include <algorithm> #define pb push_back #define mp make_pair #define LL long long #define lson lo,mi,rt<<1 #define rson mi+1,hi,rt<<1|1 #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define mem0(a) memset(a,0,sizeof(a)) #define mem1(a) memset(a,-1,sizeof(a)) #define mem(a,b) memset(a,b,sizeof(a)) #define FIN freopen("in.txt", "r", stdin) #define FOUT freopen("out.txt", "w", stdout) using namespace std; const int mod = 1e9 + 7; const double eps = 1e-8; const double ee = exp(1.0); const int inf = 0x3f3f3f3f; const int maxn = 100000 + 10; const double pi = acos(-1.0); const LL iinf = 0x3f3f3f3f3f3f3f3f; int readT() { char c; int ret = 0,flg = 0; while(c = getchar(), (c < '0' || c > '9') && c != '-'); if(c == '-') flg = 1; else ret = c ^ 48; while( c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c ^ 48); return flg ? - ret : ret; } struct Edge { int to, rev; LL cap; Edge(int to, LL cap, int rev):to(to),cap(cap),rev(rev){} }; vector<Edge> g[maxn]; //图的邻接表 int lev[maxn]; //顶点到源点的距离标号 int iter[maxn]; //当前弧,在其之前的边已经没用了 //向图中加入一条从fr到to的容量为cap的边 void addEdge(int fr, int to, LL cap) { g[fr].pb(Edge(to, cap, g[to].size())); g[to].pb(Edge(fr, 0, g[fr].size() - 1)); } //bfs计算从源点出发的距离标号 void bfs(int s) { mem1(lev); queue<int> q; lev[s] = 0; q.push(s); while (!q.empty()) { int v = q.front(); q.pop(); for (int i = 0; i < g[v].size(); i++) { Edge& e = g[v][i]; if (0 < e.cap && lev[e.to] == -1) { lev[e.to] = lev[v] + 1; q.push(e.to); } } } } //dfs找增广路径 LL dfs(int v, int t, LL f) { if (v == t) return f; int sz = g[v].size(); for (int& i = iter[v]; i < sz; i++) { Edge& e = g[v][i]; if (0 < e.cap && lev[v] < lev[e.to]) { LL d = dfs(e.to, t, Min(f, e.cap)); if (d) { e.cap -= d; g[e.to][e.rev].cap += d; return d; } } } return 0; } LL maxFlow(int s, int t) { LL flow = 0; while (1) { bfs(s); if (lev[t] < 0) return flow; mem0(iter); LL f; while ((f = dfs(s, t, inf)) > 0) flow += f; } } int vertexNum, vis[maxn]; //遍历残余网络找点 void minCut(int v) { int sz = g[v].size(); for (int i = 0; i < sz; i++) { Edge& e = g[v][i]; if (!vis[e.to] && 0 < e.cap) { vis[e.to] = true; vertexNum++; minCut(e.to); } } } int main() { #ifdef LOCAL FIN; #endif // LOCAL int n, m; while (~scanf("%d%d", &n, &m)) { for (int i = 0; i <= n + 1; i++) g[i].clear(); LL sum = 0; int s = 0, t = n + 1; for (int i = 1; i <= n; i++) { int x = readT(); if (x < 0) { addEdge(i, t, -x); } else { sum += x; addEdge(s, i, x); } } for (int i = 1; i <= m; i++) { int fr = readT(); int to = readT(); addEdge(fr, to, inf); } sum -= maxFlow(s, t); vertexNum = 0; mem0(vis); vis[s] = true; minCut(s); //-汇点 printf("%d %lld\n", vertexNum, sum); } return 0; }
相关文章推荐
- android stuio中assets文件夹在哪里?
- hdu1698 Just a Hook (线段树区间更新 懒惰标记)
- HDU 5372 Segment Game (MUT#7 树状数组+离散化)
- Android App 性能评测与调优
- HDU3232 Crossing Rivers 数学期望问题
- [图片]
- python字符串格式化
- [IOS 开发] 防止button被点击多次
- AMD开发新Linux显卡驱动 缩小与英伟达差距
- ubuntu rm 恢复
- Unity3D使用LitJson解析服务器上的JSON
- Win10 VMware无法上网
- 用手机访问本地环境的利器ngrok
- 平台AppKey ID
- PHP 中$_SERVER 详细介绍
- spring-mybatis.xml配置文件,spring与mybatis整合在一起
- 12Lync2013升级到SkypeForBusiness2015--客户端版本控制及用户迁移
- hdu-1162 Eddy's picture
- 多线程基础
- hdu 3336 Count the string KMP+DP