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

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8/26 网络流Dinic算法+最小割+cf相关的知识,希望对你有一定的参考价值。

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

P3254 圆桌问题

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

#include<bits/stdc++.h>
#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;



最小割

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

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

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

#include<bits/stdc++.h>
#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;



C. Directional Increase

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

#include<bits/stdc++.h>
#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;



D. Fake Plastic Trees

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

以上是关于8/26 网络流Dinic算法+最小割+cf的主要内容,如果未能解决你的问题,请参考以下文章

网络流Dinic(本篇介绍最大流)

网络流二·最大流最小割定理(Dinic模板+dfs/bfs找S集合模板)

POJ 3469(Dual Core CPU-最小割)[Template:网络流dinic V2]

UVa 1660 电视网络(点连通度+最小割最大流+Dinic)

P3376 网络流-最大流模板题(Dinic+当前弧优化)

培训补坑(day3:网络流&最小割)