poj 2987 最大权闭合图 最大流最小割模板
来源:互联网 发布:顾家家居怎么样知乎 编辑:程序博客网 时间:2024/06/08 02:23
题意:
有一公司,公司里每个人都有自己的贡献值和自己的下属,下属也有下属。
现在要裁员,每裁掉一个人,他的下属也要被裁掉,下属的下属依次类推也要裁掉。
现在问,最小的裁员量和裁员完了以后最大的贡献值。
解析:
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;}
0 0
- POJ 2987 最大流最小割最大权闭合图
- poj 2987 最大权闭合图 最大流最小割模板
- POJ 2987 Firing (最大权闭合图,最小割)
- POJ 2987 (最大权闭合图 最小割)
- POJ 2987 Firing 最小割(最大权闭合子图)
- 最大权闭合图 BZOJ 1497 最大获利 (最小割)
- 【NOI2006】最大获利 最大权闭合图+最小割
- noi 2006 最大收益 最大权闭合图转最小割转最大流
- BZOJ_P1497&Codevs_P1789 最大获利(最大权闭合图最小割最大流)
- pku2987 最小割,最大权闭合图
- 最小割---最大权闭合图简介
- 网络流-最大权闭合图(最小割求解)
- poj 2987(最大权闭合图)最小割求解:关键是思路
- poj 2987(最大权闭合图+割边最少)
- [NOI2006]最大获利(最大权闭合图 最小割应用)
- bzoj1497: [NOI2006]最大获利(最大权闭合子图,最小割)
- 最小割模型——最大权闭合子图 【NOI2006】bzoj1497 最大获利
- [最大权闭合子图 & 最小割] BZOJ1497: [NOI2006] 最大获利
- 对继承的再次理解
- this关键字
- hdu1698 Just a Hook (线段树区间更新 懒惰标记)
- c语言运算符优先级表
- 普利姆-求最小生成树
- poj 2987 最大权闭合图 最大流最小割模板
- Mysqldump参数大全
- 只会左键断点?是时候试试这样那样断点了
- Linux下各种压缩文件的解压命令(更新)
- nltk对中文进行处理和分析
- 内存映射文件的方式进行进程间通信
- 个人Yii遇到的一些小问题积累
- C++ string类 总结
- 路由配置相关知识