码迷,mamicode.com
首页 > 其他好文 > 详细

POJ2125 Destroying The Graph 二分图 + 最小点权覆盖 + 最小割

时间:2014-08-11 21:08:52      阅读:329      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   使用   os   io   

思路来源:http://blog.csdn.net/lenleaves/article/details/7873441

 

求最小点权覆盖,同样求一个最小割,但是要求出割去了那些边,
只要用最终的剩余网络进行一次遍历就可以了,比较简单。
建图:同样是一个二分图,左边的点代表去掉出边,
右边的点代表去掉入边(小心别弄混),左边去掉出边的点与源点相连,
容量为wi- 。
然后更据给出的弧进行连线,权值为INF
 
使用很好理解的EK算法:(360MS)
//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
#include <stdio.h>
#include <iostream>
#include <climits>
#include <cstring>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define mm(a) memset((a),0,sizeof((a)))
#define ll long long
using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 220;

queue <int> que;

int vis[MAXN], res[MAXN], pre[MAXN];
int n, m, map[MAXN][MAXN];
int src, des;
stack <int> ss;

bool bfs(int src, int des){
    int index;
    memset(pre, -1, sizeof(pre));
    while(!que.empty()) que.pop();
    pre[src] = 0;
    que.push(src);
    while(!que.empty()){
        index = que.front();
        que.pop();
        for(int i = src; i <= des; ++i){
            if(pre[i] == -1 && map[index][i] > 0){
                pre[i] = index;
                if(i == des)    return true;
                que.push(i);
            }
        }
    }
    return false;
}

int MaxFlow(int src, int des){
    int i, maxflow = 0;
    while(bfs(src, des)){
        int minflow = INF;
        for(i = des; i != src; i = pre[i])
            minflow = min(minflow, map[pre[i]][i]);
        for(i = des; i != src; i = pre[i]){
            map[pre[i]][i] -= minflow;
            map[i][pre[i]] += minflow;
        }
        maxflow += minflow;
    }
    return maxflow;
}

void init(){
    mm(map);mm(vis);
}

void dfs(int p){
    if(vis[p]) return ;
    vis[p] = true;
    for(int i = src; i < des; ++i)
        if(!vis[i] && map[p][i]) dfs(i);
}

void solve(){
    int i, x, y, ans = 0, temp;
    init();
    for(i = 1; i <= n; ++i)
        scanf("%d",&map[n + i][n * 2 + 1]);
    for(i = 1; i <= n; ++i)
        scanf("%d",&map[0][i]);
    for(i = 1; i <= m; ++i){
        scanf("%d%d",&x,&y);
        map[x][y + n] = INF;
    }

    n = n << 1;
    src = 0, des = n + 1;
    ans = MaxFlow(src, des);

    dfs(0);

    printf("%d\n",ans);
    n = n >> 1;

    for(i = 1; i <= n; ++i){
        if(!vis[i])
            ss.push(i);
        if(vis[i + n])
            ss.push(i + n);
    }
    printf("%d\n",ss.size());
    while(!ss.empty()){
        temp = ss.top();
        ss.pop();
        if(temp <= n)   printf("%d -\n",temp);
        else    printf("%d +\n",temp - n);
    }
}

int main(){
    while(EOF != scanf("%d%d",&n,&m))    solve();
    return 0;
}

 


使用SAP + GAP 优化:(79MS) 
//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
#include <stdio.h>
#include <iostream>
#include <climits>
#include <cstring>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define mm(a) memset((a),0,sizeof((a)))
#define ll long long
using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 220;

int n, m, map[MAXN][MAXN], dis[MAXN], gap[MAXN];
int src, des;
bool vis[MAXN];
stack <int> ss;

void init(){
    mm(dis);mm(gap);mm(map);mm(vis);
}

int sap(int u,int flow){
    if(u == des) return flow;
    int ans = 0, i, t;
    for(i = 0; i <= n + 1; ++i)
        if(map[u][i] && dis[u] == dis[i] + 1){
            t = sap(i, min(flow - ans, map[u][i]));
            map[u][i] -= t, map[i][u] += t,ans += t;
            if(ans == flow) return ans;
        }
    if(dis[src] >= n + 2) return ans;
    if(!--gap[dis[u]]) dis[src] = n + 2;
    ++gap[++dis[u]];
    return ans;
}

void dfs(int p){
    if(vis[p]) return ;
    vis[p] = true;
    for(int i = 0; i < n + 1; ++i)
        if(!vis[i] && map[p][i]) dfs(i);
}

void solve(){
    int i, x, y, ans = 0, temp;
    init();
    for(i = 1; i <= n; ++i)
        scanf("%d",&map[n + i][n * 2 + 1]);
    for(i = 1; i <= n; ++i)
        scanf("%d",&map[0][i]);
    for(i = 1; i <= m; ++i){
        scanf("%d%d",&x,&y);
        map[x][y + n] = INF;
    }

    n = n << 1;
    src = 0, des = n + 1;
    for(gap[0] = n + 2; dis[src] < n + 2; )
        ans += sap(src,INF);

    dfs(0);

    printf("%d\n",ans);
    n = n >> 1;

    for(i = 1; i <= n; ++i){
        if(!vis[i])
            ss.push(i);
        if(vis[i + n])
            ss.push(i + n);
    }
    printf("%d\n",ss.size());
    while(!ss.empty()){
        temp = ss.top();
        ss.pop();
        if(temp <= n)   printf("%d -\n",temp);
        else    printf("%d +\n",temp - n);
    }
}

int main(){
    while(scanf("%d%d",&n,&m)!=EOF)    solve();
    return 0;
}

 

POJ2125 Destroying The Graph 二分图 + 最小点权覆盖 + 最小割,布布扣,bubuko.com

POJ2125 Destroying The Graph 二分图 + 最小点权覆盖 + 最小割

标签:des   style   blog   http   color   使用   os   io   

原文地址:http://www.cnblogs.com/wushuaiyi/p/3905481.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!