第十三周:[Sicily]1423. 魔王bug的2色定理

最小割。求最小数量的端点为不同颜色(黑白)的边,可以将黑点视为一个集合,白点视为一个集合,求两个集合相连的最小可能边数,其实就是最小割,但由于白黑点可能有很多个,需要一个源点指向所有黑点,所有白点指向汇点,这些边的容量均为INF,然后在图中求最大流,即最小割


#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

int m,n,map[202][202];

int find_max_flow(){
    bool findpath = true;
    int ans = 0;
    while(findpath){
        bool visit[202] = {false};
        int pre[202] = {-1},cur_flow,pre_flow,cur_point;
        queue<int> q;
        q.push(0);
        visit[0] = true;
        findpath = false;
        while(!q.empty()){
            int now = q.front(),i;
            q.pop();
            if(map[now][n+1] > 0){
                findpath = true;
                cur_point = now;
                cur_flow = map[cur_point][n+1];
                while(pre[cur_point] != 0){
                    pre_flow = map[pre[cur_point]][cur_point];
                    cur_flow = cur_flow > pre_flow ? pre_flow : cur_flow;
                    cur_point = pre[cur_point];
                }
                ans += cur_flow;
                map[now][n+1] -= cur_flow;
                map[n+1][now] += cur_flow;
                while(pre[now] != 0){
                    map[pre[now]][now] -= cur_flow;
                    map[now][pre[now]] += cur_flow;
                    now = pre[now];
                }
                break;
            }
            for(i = 1;i <= n;i++)
                if(map[now][i] > 0 && visit[i] == false){
                    q.push(i);
                    pre[i] = now;
                    visit[i] = true;
            }
        }
    }
    return ans;
}

int main(){
    int INF = 400;
    while(cin>>n>>m){
        int i,a,b,h;
        memset(map,0, sizeof(map));
        for(i = 0;i < m;i++){
            cin>>a>>b;
            map[a][b] = 1;
            map[b][a] = 1;
        }
        cin>>h;
        for(i = 0;i < h;i++){
            cin>>a;
            map[0][a] = INF;
            map[a][0] = INF;
        }
        cin>>b;
        for(i = 0;i < b;i++){
            cin>>a;
            map[a][n+1] = INF;
            map[n+1][a] = INF;
        }
        cout<<find_max_flow()<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值