• 网络流24题


    P2756 飞行员配对方案问题

    简单二分图匹配

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    const int N=1e3+5;
    int gp[N][N],match[N],vis[N];
    int n,m;
    bool findpath(int u){
        for(int i=m+1;i<=n+m;i++){
            if(gp[u][i]&&!vis[i]){
                vis[i]=1;
                if(!match[i]||findpath(match[i])){
                    match[i]=u;
                    return 1;
                }
            }
        }
        return 0;
    }   
    void init(){
        memset(gp,0,sizeof gp);
        memset(match,0,sizeof match);
    }
    int main(){
        init();
        scanf("%d %d",&m,&n);
        int u,v;
        while(~scanf("%d %d",&u,&v)){
            if(u+v<0)break;
            gp[u][v]=1;
        }
        vector<int>ans;
        for(int i=1;i<=m;i++){
        
            memset(vis,0,sizeof vis);
            if(findpath(i))ans.pb(i);
        
        }
        for(int i=m+1;i<=n+m;i++){
            if(match[i])match[ match[i] ]=i;
        }
        cout<<ans.size()<<endl;
        for(int i=0;i<ans.size();i++){
            printf("%d %d
    ",ans[i],match[ ans[i] ]);
        }
    
        // system("pause");
        return 0;
    }
    View Code

    P4015 运输问题

    easy

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e4+50;
    const int inf=0x3f3f3f3f;
    int a[200],b[200],c[200][200];
    int n,m,S,T;
    int mincost;
    struct Dinic{
        int head[N],dis[N],pre[N],flow[N],last[N];
        bool inq[N];
        int ecnt; 
        struct edge{
            int v,w,flow,next;
        }e[N*10];
        void init(){
            memset(head,-1,sizeof head);
            ecnt = 0;
        }
        void addedge(int u,int v,int w,int flow){
        e[ecnt].v=v;e[ecnt].w=w;e[ecnt].flow=flow;e[ecnt].next=head[u];head[u]=ecnt++;
        }
    
        bool spfa(){
            memset(dis,inf,sizeof dis);
            memset(flow,inf,sizeof flow);
            memset(inq,0,sizeof inq);
            queue<int>Q;
            Q.push(S);inq[S]=1;dis[S]=0;pre[T]=-1;
            while(!Q.empty()){
                int u=Q.front();Q.pop();inq[u]=0;
                for(int i=head[u];~i;i=e[i].next){
                    int v=e[i].v,w=e[i].w;
                    if(e[i].flow>0&&dis[v]>dis[u]+w){
                        dis[v]=dis[u]+w;pre[v]=u;last[v]=i;
                        flow[v]=min(flow[u],e[i].flow);
                        if(!inq[v]){
                        Q.push(v);inq[v]=1;
                        }
                    }
                }
            }
            return pre[T]!=-1;
        }
        void  MCMF(){
            mincost=0;
            while(spfa()){
                int cur=T;
                mincost+=flow[T]*dis[T];
                while(cur!=S){
                    e[last[cur]].flow-=flow[T];
                    e[last[cur]^1].flow+=flow[T];
                    cur=pre[cur];
                }
            }
        }
    
    }dinic;  
    
    void init_add(int t){
        for(int i=1;i<=m;i++){
            dinic.addedge(S,i,0,a[i]);
            dinic.addedge(i,S,0,0);
        }
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                dinic.addedge(i,j+m,t*c[i][j],inf);
                dinic.addedge(j+m,i,-c[i][j]*t,0);
            }
        }
        for(int i=1;i<=n;i++){
            dinic.addedge(i+m,T,0,b[i]);
            dinic.addedge(T,i+m,0,0);
        }
    }
    int main(){
        scanf("%d %d",&m,&n);
        S=0,T=10005;
        for(int i=1;i<=m;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)scanf("%d",&b[i]);
            for(int i=1;i<=m;i++){
                for(int j=1;j<=n;j++){
                    scanf("%d",&c[i][j]);
                }
            }
    
            dinic.init();
            init_add(1);
            dinic.MCMF();
            printf("%d
    ",mincost);
    
            dinic.init();
            init_add(-1);
            dinic.MCMF();
    
            printf("%d
    ",-mincost);
            // system("pause");
        return 0;
    }
    View Code

    P2764 最小路径覆盖问题

    考虑最初有n个路径穿过n个点,那么如果两两之间有边,就可以把路径合并,做法就是把每个点拆成两个点,如果有边就连一下,表示联通。

    跑一遍最大流,实际上就是合并尽可能多的路径。

     输出路径:把一条路径的点合并到一个并查集里,然后起点标记为父结点,递归输出。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+5;
    const int inf=0x3f3f3f3f;
    struct edge{int v,next;}e[N*10];
    int n,m,S,T;
    struct Dinic{
        int head[N],dep[N];
        int ecnt; 
        struct edge{
            int v,flow,next;
        }e[N*10];
    
        void init(){
            memset(head, -1, sizeof head);
            ecnt = 0;
        }
    
        void addedge(int u, int v, int  flow) {
        e[ecnt].v=v;e[ecnt].flow=flow;e[ecnt].next=head[u];head[u]=ecnt++;
        e[ecnt].v=u;e[ecnt].flow=0;e[ecnt].next=head[v];head[v]=ecnt++;
        }
    
        bool BFS(){//分层图找增广路
            memset(dep,0,sizeof dep);
            queue<int>Q;
            Q.push(S);dep[S]=1;
            while(!Q.empty()){
                int u=Q.front();Q.pop();
                for(int i=head[u];~i;i=e[i].next){
                    if(e[i].flow&&!dep[e[i].v]){
                        dep[e[i].v]=dep[u]+1;
                        Q.push(e[i].v);
                    }
                }
            }
            return dep[T];
        }
    
        int DFS(int u, int f){//推进新流
            if(u==T||f==0)return f;
            int w,used=0;
            for(int i=head[u];~i;i=e[i].next){
                if(e[i].flow&&dep[e[i].v]==dep[u]+1){
                    w=DFS(e[i].v,min(f,e[i].flow));//多路增广
                    e[i].flow-=w;e[i^1].flow+=w;
                    used+=w;f-=w;
                }
            }
            if(!used)dep[u]=-1;//炸点优化
            return used;
        }
    
        int maxflow() {
            int ans=0;
            while(BFS()){
                ans+=DFS(S,inf);
            }
            return ans;
        }
    
        int fa[N];
        int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
        void build(int x,int y){int dx=find(x),dy=find(y);if(dx!=dy)fa[dx]=dy;}
        
        void print(int u){
            printf("%d ",u);
            for(int i=head[u];~i;i=e[i].next){
                if(e[i].flow==0&&e[i].v>n){
                    print(e[i].v-n);
                }
            }
        }
        
        void work(){
            for(int i=1;i<=n;i++)fa[i]=i;
            int ans=maxflow();
                for(int u=1;u<=n;u++){
                    for(int i=head[u];~i;i=e[i].next){
                        // if(e[i].v==T)continue;
                        if(e[i].flow==0&&e[i].v>n){
                            build(e[i].v-n,u);
                        }
                    }
                
                }
    
            for(int cur=1;cur<=n;cur++){
                if(find(cur)==cur){print(cur);puts("");}
            }
    
            printf("%d
    ",n-ans);
        }
    }dinic;  
    int main(){
        scanf("%d %d",&n,&m);
        dinic.init();
        S=0,T=2*n+50;
        
        int u,v;
        while(m--){
            scanf("%d %d",&u,&v);
            dinic.addedge(u,v+n,1);
        }
        
        for(int i=1;i<=n;i++){
            dinic.addedge(i+n,T,1);
        }
        for(int i=1;i<=n;i++){
            dinic.addedge(S,i,1);
        }
        dinic.work();
        // system("pausea");
        return 0;
    }
    View Code 

    P1251 餐巾计划问题

  • 相关阅读:
    shell脚本之for循环
    shell脚本小集锦
    Java构建指定大小文件
    IntelliJ+Maven+Spring+Tomcat项目搭建(MAC)
    Git下基本命令操作
    Mac下IntelliJ的Git、GitHub配置及使用
    Git下的.DS_Store文件
    Mac下GitHub以及GitHub Desktop使用实战
    idea快捷键
    汉字获取首字符
  • 原文地址:https://www.cnblogs.com/littlerita/p/12869851.html
Copyright © 2020-2023  润新知