• AcWing2325 有向图破坏(最小权点覆盖)


    二分图的最小权点覆盖问题可以使用最小割模型求解

    在求具体方案的时候,首先找到割集,也就是从源点搜出去,之后判断两边访问情况求点覆盖

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+10;
    const int inf=1e8;
    int h[N],ne[N],e[N],idx,f[N];
    int S,T;
    int st[N];
    int d[N],cur[N];
    void add(int a,int b,int c){
        e[idx]=b,ne[idx]=h[a],f[idx]=c,h[a]=idx++;
        e[idx]=a,ne[idx]=h[b],f[idx]=0,h[b]=idx++;
    }
    int bfs(){
        memset(d,-1,sizeof d);
        d[S]=0;
        cur[S]=h[S];
        queue<int> q;
        q.push(S);
        while(q.size()){
            int t=q.front();
            q.pop();
            for(int i=h[t];i!=-1;i=ne[i]){
                int j=e[i];
                if(d[j]==-1&&f[i]){
                    cur[j]=h[j];
                    d[j]=d[t]+1;
                    if(j==T)
                    return true;
                    q.push(j);
                }
            }
        }
        return false;
    }
    int find(int u,int limit){
        if(u==T){
            return limit;
        }
        int i;
        int flow=0;
        for(i=cur[u];i!=-1&&flow<limit;i=ne[i]){
            cur[u]=i;
            int j=e[i];
            if(d[j]==d[u]+1&&f[i]){
                int t=find(j,min(f[i],limit-flow));
                if(!t)
                d[j]=-1;
                else{
                    f[i]-=t;
                    f[i^1]+=t;
                    flow+=t;
                }
                    
            }
        }
        return flow;
    }
    int dinic(){
        int flow;
        int r=0;
        while(bfs()){
            while(flow=find(S,inf))
                r+=flow;
        }
        return r;
    }
    void dfs(int u)
    {
        st[u] = true;
        for (int i = h[u]; ~i; i = ne[i])
            if (f[i] && !st[e[i]])
                dfs(e[i]);
    }
    int main(){
        ios::sync_with_stdio(false);
        memset(h,-1,sizeof h);
        int i;
        int n,m;
        cin>>n>>m;
        S=0,T=2*n+1;
        for(i=1;i<=n;i++){
            int x;
            cin>>x;
            add(S,i,x);
        }
        for(i=1;i<=n;i++){
            int x;
            cin>>x;
            add(i+n,T,x);
        }
        for(i=1;i<=m;i++){
            int a,b;
            cin>>a>>b;
            add(b,a+n,inf);
        }
        cout<<dinic()<<endl;
        dfs(S);
        int cnt=0;
        for(i=0;i<idx;i+=2){
            int b=e[i],a=e[i^1];
            if(st[a]&&!st[b])
            cnt++;
        }
        cout<<cnt<<endl;
        for(i=0;i<idx;i+=2){
            int b=e[i],a=e[i^1];
            if(st[a]&&!st[b]){
                if(a==S) 
                cout<<b<<" +"<<endl;
            }
        }
        for(i=0;i<idx;i+=2){
            int b=e[i],a=e[i^1];
            if(st[a]&&!st[b]){
                if(b==T)
                cout<<a-n<<" -"<<endl;
            }
        }
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    【剑指Offer】跳台阶&变态跳台阶
    【剑指Offer】替换空格
    【剑指Offer】二维数组中的查找
    【Leetcode】2. Add Two Numbers 两数相加
    HTML学习笔记(一)HTML的一些概念区别
    C#项目中一些文件类型说明
    数据结构初步归纳(一)概念、线性表以及队列和栈
    线程相关概念
    程序开发方法论
    C#集合类型
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13627597.html
Copyright © 2020-2023  润新知