• 8/26 网络流Dinic算法+最小割+cf


    Dinic算法相较于EK()算法效率更高

    P3254 圆桌问题

    思路:可用二分图来写,本题在于练习Dinic算法。
    1.建立一个超级源点,连接每个代表团,权值为每个代表团的人数;
    2.建立一个超级汇点,将每个圆桌连接汇点,权值为圆桌可容纳的人数;
    3.将每个代表团连接每个圆桌,由于每个代表团不会安排两个人去同一个圆桌,因此权值都为1.

    #include
    #define int long long
    #define endl '\n'
    #define For(i,a,b) for(i=(a);i<=(b);++i)
    #define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
    using namespace std;
    const int N=7e5+7;
    const int inf=0x3f3f3f3f;
    const int mod=1e9+7;
    struct edge
    {
        int to,c,nxt;
    }e[N];
    int n,m,r[N],c[N],s,t,sum;
    int head[N],idx=1;
    int d[N],cur[N];
    void add(int a,int b,int c)
    {
        e[++idx]={b,c,head[a]};
        head[a]=idx;
    }
    bool bfs()
    {
        memset(d,0,sizeof d);
        queue<int>q;
        q.push(s);
        d[s]=1;
        while(q.size())
        {
            int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].nxt)
            {
                int v=e[i].to;
                if(d[v]==0&&e[i].c)
                {
                    d[v]=d[u]+1;
                    q.push(v);
                    if(v==t) return 1;
                }
            }
        }
        return 0;
    }
    int dfs(int u,int mf)
    {
        if(u==t) return mf;
        int sum=0;
        for(int i=cur[u];i;i=e[i].nxt)
        {
            cur[u]=i;
            int v=e[i].to;
            if(d[v]==d[u]+1&&e[i].c)
            {
                int f=dfs(v,min(mf,e[i].c));
                e[i].c-=f;
                e[i^1].c+=f;
                sum+=f;
                mf-=f;
                if(mf==0) break;
            }
        }
        if(sum==0) d[u]=0;
        return sum;
    }
    int dinic()
    {
        int flow=0;
        while(bfs())
        {
            memcpy(cur,head,sizeof head);
            flow+=dfs(s,inf);
        }
        return flow;
    }
    void solve()
    {
        cin>>m>>n;
        s=0,t=n+m+1;
        for(int i=1;i<=m;i++)
        {
            cin>>r[i];sum+=r[i];
            add(0,i,r[i]);  //建立一个超级源点
            add(i,0,0);
        }
        for(int i=1;i<=n;i++)
        {
            cin>>c[i];
            add(i+m,t,c[i]);//建立一个超级汇点
            add(t,i+m,0);
        }
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                add(i,j+m,1);
                add(j+m,i,0);
            }
        }
        int ans=dinic();
        if(ans!=sum)
            cout<<0<<endl;
        else
        {
            cout<<1<<endl;
            for(int k=1;k<=m;k++)
            {
                for(int i=head[k];i;i=e[i].nxt)
                {
                    if(e[i].to>m&&e[i].to<=m+n&&!e[i].c)
                        cout<<e[i].to-m<<" ";
                }
                cout<<endl;
            }
        }
    }
    signed main()
    {
        //ios;
        //int T;cin>>T;
        //while(T--)
            solve();
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125

    最小割

    大佬讲解:https://www.bilibili.com/video/BV1iG411s7iX?spm_id_from=333.999.0.0&vd_source=91973ada1213cf6ba2cbb43a2bebd2e8
    最小割最大流定理:最小割的容量等于最大流的容量

    P1344 [USACO4.4]追查坏牛奶Pollutant Control

    三个问题:
    最小割、最小割的划分、最小割的最少边数
    代码:

    #include
    #define int long long
    #define endl '\n'
    #define For(i,a,b) for(i=(a);i<=(b);++i)
    #define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
    using namespace std;
    const int N=7e5+7;
    const int inf=0x3f3f3f3f;
    const int mod=1e9+7;
    struct edge
    {
        int to,c,nxt;
    }e[N];
    int n,m,a[N],b[N],s,t;
    int head[N],idx=1;
    int d[N],cur[N];
    void add(int a,int b,int c)
    {
        e[++idx]={b,c,head[a]};
        head[a]=idx;
    }
    bool bfs()
    {
        memset(d,0,sizeof d);
        queue<int>q;
        q.push(s);
        d[s]=1;
        while(q.size())
        {
            int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].nxt)
            {
                int v=e[i].to;
                if(d[v]==0&&e[i].c)
                {
                    d[v]=d[u]+1;
                    q.push(v);
                    if(v==t) return 1;
                }
            }
        }
        return 0;
    }
    int dfs(int u,int mf)
    {
        if(u==t) return mf;
        int sum=0;
        for(int i=cur[u];i;i=e[i].nxt)
        {
            cur[u]=i;
            int v=e[i].to;
            if(d[v]==d[u]+1&&e[i].c)
            {
                int f=dfs(v,min(mf,e[i].c));
                e[i].c-=f;
                e[i^1].c+=f;
                sum+=f;
                mf-=f;
                if(mf==0) break;
            }
        }
        if(sum==0) d[u]=0;
        return sum;
    }
    int dinic()
    {
        int flow=0;
        while(bfs())
        {
            memcpy(cur,head,sizeof head);
            flow+=dfs(s,inf);
        }
        return flow;
    }
    bool vis[N];
    void mincut(int u)
    {
        vis[u]=1;
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(!vis[v]&&e[i].c)
                mincut(v);
        }
    }
    void solve()
    {
        cin>>m>>n;
        s=1,t=n;
        for(int i=1,c;i<=m;i++)
        {
            cin>>a[i]>>b[i]>>c;
            add(a[i],b[i],c);
            add(b[i],a[i],0);
        }
        //最小割的容量
        cout<<dinic()<<endl;
        //最小割的划分
        for(int i=1;i<=n;i++)   // S
            if(vis[i])
                cout<<i<<" ";
        for(int i=1;i<=n;i++)   // T
            if(!vis[i])
                cout<<i<<" ";
        //最小割最少边数
        idx=1;
        memset(head,0,sizeof head);
        for(int i=1;i<=m;i++)
        {
            add(a[i],b[i],1);
            add(b[i],a[i],0);
        }
        cout<<dinic()<<endl;
    }
    signed main()
    {
        //ios;
        //int T;cin>>T;
        //while(T--)
            solve();
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124

    C. Directional Increase

    思路:
    1.可通过加一移动到下一个元素,也可通过减1操纵移动到前一个元素,由于是从1开始,最后回到位置1,因此前缀和必定是>=0的。
    2.在最后后一个非0元素由于要回到1,因此肯定为负数,前缀和肯定为0.

    #include
    #define int long long
    #define endl '\n'
    #define For(i,a,b) for(i=(a);i<=(b);++i)
    #define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
    using namespace std;
    const int N=1e6+7;
    const int inf=0x3f3f3f3f;
    const int mod=1e9+7;
    int n,a[N],sum[N];
    void solve()
    {
        cin>>n;
        for(int i=0;i<=n;i++)
            sum[i]=0;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        for(int i=1;i<=n;i++)
            sum[i]=sum[i-1]+a[i];
        int flag=1,idx=1;
        for(int i=n;i>=1;i--)
        {
            if(a[i])
            {
                idx=i;break;
            }
        }
        if(sum[n]) flag=0;
        for(int i=1;i<=n;i++)
        {
            if(sum[i]<=0&&i!=idx)
            {
                flag=0;break;
            }
            else if(i==idx)
                break;
        }
        if(flag)
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    }
    signed main()
    {
        //ios;
        int T;cin>>T;
        while(T--)
            solve();
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    D. Fake Plastic Trees

    思路:
    1.贪心思想,需要对每个叶子结点都操作一次,本条路径上所有经过的点都加上该值。
    2.利用深搜,若大于r[u],则返回r[u];若大于l[u],则返回累加值s
    3.若都不满足,需要再进行一次操作,返回r[u]

    #include
    #define int long long
    #define endl '\n'
    #define For(i,a,b) for(i=(a);i<=(b);++i)
    #define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
    using namespace std;
    const int N=1e6+7;
    const int inf=0x3f3f3f3f;
    const int mod=1e9+7;
    int n,cnt,head[N],l[N],r[N],ans;
    struct node
    {
        int to,nxt;
    }e[N];
    void add(int from,int to)
    {
        e[++cnt].to=to;
        e[cnt].nxt=head[from];
        head[from]=cnt;
    }
    int dfs(int u,int fa)
    {
        int s=0;
        for(int i=head[u];i;i=e[i].nxt)
        {
            int j=e[i].to;
            if(j==fa) continue;
            s+=dfs(j,u);
        }
        if(head[u]==-1)
        {
            ans++;return r[u];
        }
        if(s>=r[u]) return r[u];
        if(s>=l[u]) return s;
        ans++;
        return r[u];
    }
    void solve()
    {
        cin>>n;
        cnt=ans=0;
        for(int i=0;i<=n;i++)
            head[i]=0;
        for(int i=2;i<=n;i++)
        {
            int x;cin>>x;
            add(x,i);
        }
        for(int i=1;i<=n;i++)
            cin>>l[i]>>r[i];
        dfs(1,0);
        cout<<ans<<endl;
    }
    signed main()
    {
        //ios;
        int T;cin>>T;
        while(T--)
            solve();
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
  • 相关阅读:
    为什么机加工行业需要建设生产运营管理系统
    Jenkins环境搭建
    渗透测试-子域名发现
    易观千帆 | 2022年10月银行APP月活跃用户规模盘点
    基于Python开发的飞机大战小游戏彩色版(源码+可执行程序exe文件+程序配置说明书+程序使用说明书)
    Qt的Pro文件
    Hadoop组成、HDFS、YARN、 MapReduce、 Hadoop环境搭建
    如何修复 Windows 11/10上的 0x8007023e Windows 更新错误
    【学习笔记】POJ 3834 graph game
    块设备 I/O 请求送达到外部设备
  • 原文地址:https://blog.csdn.net/weixin_51934288/article/details/126524838