poj 2987 Firing 最大权闭合子图
2017-02-14 22:46
726 查看
参见文献:
最小割模型在比赛中的运用
这是最大权闭合子图问题,参见以上文献.
建边,
s->i if b[i]>0;
i->t if b[i]<0;
i->j if j是i的下属
费用就等于
∑b[i]>0b[i]−max−flow
与S相连接的点为裁掉的人员
最小割模型在比赛中的运用
这是最大权闭合子图问题,参见以上文献.
建边,
s->i if b[i]>0;
i->t if b[i]<0;
i->j if j是i的下属
费用就等于
∑b[i]>0b[i]−max−flow
与S相连接的点为裁掉的人员
#include <cstdio> #include <iostream> #include <vector> #include <queue> #include <algorithm> #include <cmath> #include <cstring> #include <map> #include <set> #include <stack> #define fi first #define se second #define INF 0x3f3f3f3f #define INF64 0x3f3f3f3f3f3f3f3f using namespace std; typedef long long LL; typedef pair<int,int> Pair; const int maxn = 5000+10; const int MAX_V = 5000+10; struct Edge{ int from,to;//原图的边 LL cap; Edge(int u,int v,LL c = 0):from(u),to(v),cap(c){}; }; std::vector<Edge> E; std::vector<int> G[MAX_V]; //残量网络 void add_edge(int u,int v,LL cap){ E.push_back(Edge(u,v,cap));G[u].push_back(E.size()-1); E.push_back(Edge(v,u,0)); G[v].push_back(E.size()-1); } struct Dinic{ int level[MAX_V],cur[MAX_V];//分层,当前弧; void bfs(int s){ memset(level,-1,sizeof(level)); queue<int> Q;Q.push(s); level[s] = 0; while (!Q.empty()) { int u = Q.front();Q.pop(); 4000 for(int i=0 ; i<G[u].size() ; ++i){ Edge & e = E[G[u][i]]; if(e.cap>0 && level[e.to]<0){ level[e.to] = level[u]+1; Q.push(e.to); } } } } LL dfs(int v,int t,LL f){ if(v==t || f == 0)return f; for(int& i = cur[v] ; i<G[v].size() ; ++i){ Edge & e = E[G[v][i]];Edge & rev = E[G[v][i]^1]; if(e.cap>0 && level[v]<level[e.to]){ LL a = dfs(e.to,t,min(f,e.cap)); if(a>0){ e.cap-=a; rev.cap+=a; return a; } } } return 0; } LL max_flow(int s,int t){ LL flow = 0; for(;;){ bfs(s); if(level[t]<0)break; memset(cur,0,sizeof(cur)); LL f; while ((f = dfs(s,t,INF64))>0) { flow+=f; } } return flow; } }; LL b[maxn]; Dinic Flow; bool mark[MAX_V]; int cnt =0; void dfs(int s){ mark[s] = true;cnt++; for(int i=0 ; i<G[s].size() ; ++i){ Edge & e = E[G[s][i]]; if( e.cap>0&& !mark[e.to])dfs(e.to); } } int main() { int n,m; scanf("%d%d",&n,&m ); for(int i=1 ; i<=n ; ++i)scanf("%lld",&b[i] ); while (m--) { int x,y; scanf("%d%d",&x,&y ); add_edge(x,y,INF64); } int s = 0,t = n+1; LL sum = 0; for(int i=1 ; i<=n ; ++i) { if(b[i]>0){add_edge(s,i,b[i]);sum+=b[i];} else add_edge(i,t,-b[i]); } LL profit = sum-Flow.max_flow(s,t); memset(mark,false,sizeof(mark)); cnt = 0; dfs(s); printf("%d %lld\n",--cnt,profit ); return 0; }
相关文章推荐
- poj 2987 Firing (最大权闭合子图)
- POJ 2987 Firing 最大权闭合子图
- POJ 2987 Firing(最大权闭合子图)
- poj 2987 Firing【最大闭合子图】
- POJ 2987 Firing (最大权闭合子图Dinic)
- 【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【最大权闭合子图+玄学计数 || BFS】
- poj 2987 Firing 最大权闭合图
- poj 2987 Firing 最大权闭合图
- POJ 2987 Firing 最大权闭合图
- POJ 2987 Firing(最大流最小割の最大权闭合图)
- POJ 2987 Firing(最大权闭合图)
- poj 2987 Firing 最大权闭合图