POJ 2987 Firing 最大权闭合子图
2014-09-08 16:49
519 查看
题意:有N个人,M个人的前后上下级关系。当你解雇一个人时,他的下级会被全部解雇。解雇每个人有收益,可能为正或为负。求出最大收益。同时求出裁员的最小人数。
思路:问题中出现了前后依赖关系,我们很容易想到最大权闭合子图。直接利用最大权闭合子图模型,我们可以求出最大的收益。现在问题是如何求出最小的裁员人数。
我们先考虑为什么会出现裁员的最小人数。因为,虽然最小割的容量是唯一的,但是,可能因为流网络结构的不同,导致最小割的边的集合是不唯一的,这就导致我们可以选择多种st割,让位于S集合的点的数目不同,从而出现了最小的S集合。
为了求出最小的S的集合,我们从源点S开始进行搜索,一遇到不位于残留网络的边,就不再继续向下搜索,即认为后面的点都和T相连,即最大化被留下的人。这样我们就可以最小的S的集合。BFS和DFS都可以。
代码如下:
思路:问题中出现了前后依赖关系,我们很容易想到最大权闭合子图。直接利用最大权闭合子图模型,我们可以求出最大的收益。现在问题是如何求出最小的裁员人数。
我们先考虑为什么会出现裁员的最小人数。因为,虽然最小割的容量是唯一的,但是,可能因为流网络结构的不同,导致最小割的边的集合是不唯一的,这就导致我们可以选择多种st割,让位于S集合的点的数目不同,从而出现了最小的S集合。
为了求出最小的S的集合,我们从源点S开始进行搜索,一遇到不位于残留网络的边,就不再继续向下搜索,即认为后面的点都和T相连,即最大化被留下的人。这样我们就可以最小的S的集合。BFS和DFS都可以。
代码如下:
<span style="font-size:12px;">#include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef long long ll; struct edge{ int from,to; ll cap,flow; edge(int u =0,int v =0,ll c=0LL,ll f=0LL):from(u),to(v),cap(c),flow(f){} }; struct ISAP{ static const ll INF = 0x3f3f3f3f3f3f3f3f; static const int MAX = 100010;//2倍的边的大小 int head[MAX];//每个节点对应链表的开始位置 int next[MAX];//链表的下一个节点在edges数组的位置 int tot;//edges数组的大小 edge edges[MAX];//储存边的数组 int que[MAX],front,tail;//队列,保存节点 int d[MAX];//距离标号 bool vis[MAX];//访问标记 int num[MAX];//gap优化 int pre[MAX];//增广路中,节点X的前面一个弧的标号 int cur[MAX];//对于每个节点的,处理的当前弧。 int s,t,n;//s源点标号,t汇点标号,n节点总数 int cnt; void init(int n){ this->n = n;//注意此处的下标问题 memset(head,-1,sizeof(int)*(n+1)); tot = 0;// } void addedge(int from,int to, ll cap){ edges[tot] = edge(from,to,cap,0); next[tot] = head[from], head[from] = tot++; edges[tot] = edge(to,from,0,0); next[tot] = head[to],head[to] = tot++; } void bfs(){ memset(vis,0,sizeof(vis)); front = tail = 0; d[t] = 0; vis[t] = true; que[tail++] = t; while(front < tail){ int u = que[front++]; for(int v = head[u]; v != -1; v = next[v]){ edge & e = edges[v^1]; if(e.cap > e.flow && !vis[e.from]){//对处于残余网络中的弧且没访问过的节点处理 d[e.from] = d[u] + 1; vis[e.from] = true; que[tail++] = e.from; } } } } ll augment(){ int x = t; ll a = INF; while(x != s){ edge& e = edges[pre[x]]; a = min(a,e.cap - e.flow); x = e.from; } x = t; while(x != s){ edges[pre[x]].flow += a; edges[pre[x]^1].flow -= a; x = edges[pre[x]].from; } return a; } ll maxflow(int s, int t){ this->s = s, this->t = t; memset(num,0,sizeof(num)); ll flow = 0LL; bfs(); for(int i = 0; i < n; ++i){//注意此处的下标问题 num[d[i]]++; cur[i] = head[i]; } int x = s; while(d[s] < n){ if(x == t){ flow += augment(); x = s; } bool ok = false; for(int &v = cur[x]; v != -1; v = next[v]){ edge& e = edges[v]; if(e.cap > e.flow && d[x] == d[e.to] + 1){ ok = true; pre[x = e.to] = v; break; } } if(!ok){ int m = n - 1; for(int v = head[x]; v != -1; v = next[v]){ edge & e = edges[v]; if(e.cap > e.flow) m = min(m,d[e.to]); } if(--num[d[x]] == 0) break; num[d[x]=m+1]++; cur[x] = head[x]; if(x != s) x = edges[pre[x]].from; } } return flow; } void dfs(int u){ vis[u] = true; for(int v = head[u]; ~v; v = next[v]){ edge & e = edges[v]; if(e.cap > e.flow &&!vis[e.to]){ cnt++; dfs(e.to); } } } int mincut(){ memset(vis,0,sizeof(vis)); cnt = 0; dfs(s); return cnt; } } solver; const ll INF = 0x3f3f3f3f3f3f3f3f; int T; int n,m; int s,t; ll pro; int sum; int x,y; int main(void) { //freopen("input.txt","r",stdin); ll sum = 0LL; scanf("%d %d", &n, &m); s = 0, t = n + 1; solver.init(n + 2); for(int i = 1 ; i <= n; ++i){ scanf("%lld", &pro); if(pro > 0){ solver.addedge(s,i,pro); sum += pro; } else solver.addedge(i,t,-pro); } for(int i = 0 ; i < m; ++i){ scanf("%d %d", &x, &y); solver.addedge(x,y,INF); } ll ans2 = solver.maxflow(s,t); int ans1 = solver.mincut(); printf("%d %lld\n",ans1,sum - ans2); return 0; } </span>
相关文章推荐
- 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 2987 Firing【最大权闭合子图+玄学计数 || BFS】
- POJ 2987 Firing (最大权闭合子图Dinic)
- poj 2987 Firing (最大权闭合子图)
- POJ 2987 Firing(最大权闭合图)
- poj 2987 Firing 最大权闭合图
- Firing (poj 2987 最大权闭合图)
- POJ 2987 Firing 最大权闭合图
- POJ 2987 Firing(最大流最小割の最大权闭合图)
- poj 2987 Firing 最大权闭合图