poj 2987 Firing ------最大权闭合图
来源:互联网 发布:.net 465端口发邮件 编辑:程序博客网 时间:2024/05/22 07:37
网络流里的最大权闭合图和最大密度子图还是挺有意思的
方法:s连接正权点,点权赋给边,t连接负权点,点权的绝对值赋给边,原图两点之间的边用inf64正向容量连接,逆向为0.
这样就能把每一个最小割和每一个闭合图一一对应,利用最小割的性质很好证明。然后求出最小割,用所有正权和减去得到最大获利。因为最小割把图分成了两部分,所以最后求最小人数可以用一个贪心,方法是从s出发广度优先搜索,能达到的节点都是需要开除的,这样就能统计出最大获利时的最小人数!
#include<iostream>#include<vector>#include<algorithm>#include<cstdio>#include<queue>#include<stack>#include<string>#include<map>#include<set>#include<cmath>#include<cassert>#include<cstring>#include<iomanip>using namespace std;#ifdef _WIN32#define i64 __int64#define out64 "%I64d\n"#define in64 "%I64d"#else#define i64 long long#define out64 "%lld\n"#define in64 "%lld"#endif#define FOR(i,a,b) for( int i = (a) ; i <= (b) ; i ++)#define FF(i,a) for( int i = 0 ; i < (a) ; i ++)#define FFD(i,a) for( int i = (a)-1 ; i >= 0 ; i --)#define S64(a) scanf(in64,&a)#define SS(a) scanf("%d",&a)#define LL(a) ((a)<<1)#define RR(a) (((a)<<1)+1)#define SZ(a) ((int)a.size())#define PP(n,m,a)puts("---");FF(i,n){FF(j,m)cout << a[i][j] << ' ';puts("");}#define pb push_back#define CL(Q) while(!Q.empty())Q.pop()#define MM(name,what) memset(name,what,sizeof(name))#define read freopen("in.txt","r",stdin)#define write freopen("out.txt","w",stdout)const int inf = 0x3f3f3f3f;const i64 inf64 = 0x3f3f3f3f3f3f3f3fLL;const double oo = 10e9;const double eps = 10e-8;const double pi = acos(-1.0);const int maxn=5011;const int end=5001;struct zz{ int from; int to; i64 c; int id;}zx,tz;int n,m,tx,ty;i64 pro,total;int cost[maxn];vector<zz>g[maxn];queue<int>q;int cen[maxn];bool vis[maxn];bool bfs(){ CL(q); MM(cen,-1); q.push(0); cen[0] = 0; int now,to; while(!q.empty()) { now = q.front(); q.pop(); FF(i,g[now].size()) { to = g[now][i].to; if(cen[to] == -1 && g[now][i].c > 0) { cen[to] = cen[now] + 1; q.push(to); } } } return cen[end] != -1; }i64 dfs(i64 flow = inf , int now = 0 ){ if(now == end) { return flow; } i64 temp,sum=0; int to; FF(i,g[now].size()) { to = g[now][i].to; if (g[now][i].c > 0 && flow > sum && cen[to] == cen[now] + 1 ) { temp = dfs ( min ( flow - sum , g[now][i].c ) , to ); sum += temp; g[now][i].c -= temp; g[to][g[now][i].id].c += temp; } } if(!sum) cen[now] = -1; return sum;}void dinic(){ i64 ans = 0; while(bfs()) { ans += dfs(); } pro = total - ans; return ;}void bfs2(){ int ans = 0; CL(q); MM(vis,false); vis[0] = true; q.push(0); int now,to; while(!q.empty()) { now = q.front(); q.pop(); FF(i,g[now].size()) { to = g[now][i].to; if(g[now][i].c > 0 && !vis[to] ) { vis[to] = true; ans++; q.push(to); } } } cout<<ans<<" "; return ;} int main(){ total = 0; cin>>n>>m; FOR(i,1,n) { SS(cost[i]); if(cost[i] > 0) { total += cost[i]; } } FOR(i,1,m) { SS(tx); SS(ty); zx.from = tx; zx.to = ty; zx.c = inf64; zx.id = g[ty].size(); g[tx].pb(zx); swap(zx.from,zx.to); zx.c = 0; zx.id = g[tx].size() - 1; g[zx.from].pb(zx); } FOR(i,1,n) { if(cost[i]>0) { zx.from = 0; zx.to = i; zx.c = cost[i]; zx.id = g[i].size(); g[0].pb(zx); swap(zx.from,zx.to); zx.c = 0; zx.id = g[0].size()-1; g[i].pb(zx); } else if(cost[i]<0) { zx.from = i; zx.to = end; zx.c = -cost[i]; zx.id = g[end].size(); g[i].pb(zx); swap(zx.from,zx.to); zx.c = 0; zx.id = g[i].size() - 1; g[end].pb(zx); } } dinic(); bfs2(); cout<<pro<<endl; return 0; }
- poj 2987 Firing ------最大权闭合图
- poj 2987 Firing(最大权闭合图)
- POJ 2987 Firing (最大权闭合图)
- POJ 2987 Firing 最大权闭合图
- poj 2987 Firing 最大权闭合图
- POJ 2987 Firing 最大权闭合图
- POJ 2987 Firing 最大权闭合图
- poj 2987 Firing 最大权闭合图
- POJ 2987 Firing 【最大权闭合图】
- POJ 2987 Firing(最大权闭合)
- POJ 2987 Firing(最大权闭合)
- poj Firing(最大权闭合图)
- POJ 2987 Firing (最大权闭合子图Dinic)
- poj 2987 Firing 最大权闭合图 网络流
- 【POJ】2987 Firing 最大权闭合子图
- POJ 2987 Firing (最大权闭合图,最小割)
- POJ 2987 Firing 最大权闭合子图
- poj 2987 Firing 最大权闭合子图
- 领域模型剖析
- 基於區域的圖像分割-----------區域生長
- Java编程最差实践
- 基於區域的圖像分割-----------區域分裂合並
- 自己写的一些Delphi常用函数
- poj 2987 Firing ------最大权闭合图
- 什么是 MIME Type?
- Python 学习笔记01
- drp进行中
- 详解rsync算法--如何减少同步文件时的网络传输量
- 事务
- Vector、ArrayList和Hashtable、HashMap数据结构
- 经典线程代码
- 排序算法之快速排序