zoukankan      html  css  js  c++  java
  • POJ

    题意:给一张图,现在要删去所有的边,删去一个点的所有入边和所有出边都有其对应(W_{i+})(W_{i-}).求删去该图的最小花费,并输出解
    分析:简而言之就是用最小权值的点集去覆盖所有的边.
    模型转化到网络流的建图中,将图中的边视作点,并将其一拆为二,出点作为X部,入点作为Y部,若有边(u,v)则由建边u->v+N,容量正无穷.
    将原图中的点视作边,入边的花费即建边i+N->T,容量为其花费;出边的花费建边S->i,容量也是为其花费.
    跑出S->T的最大流,|最大流| = |最小割| = |最小点权覆盖|.

    还需输出每条边的解决方案.在残余网上,与S相连的点,若满流则表示没有选择该点;与T相连的点,若满流则表示选择该点.从源点dfs一次后,再遍历从S出发和从T出发的所有弧即可.
    *其性质和最大权闭合子图很相似.

    #include<iostream>
    #include<cstring>
    #include<stdio.h>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include<vector>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int MAXN=3010;//点数的最大值
    const int MAXM=400010;//边数的最大值
    #define captype int
    
    struct SAP_MaxFlow{
        struct Edge{
            int from,to,next;
            captype cap;
        }edges[MAXM];
        int tot,head[MAXN];
        int gap[MAXN];
        int dis[MAXN];
        int cur[MAXN];
        int pre[MAXN];
    
        void init(){
            tot=0;
            memset(head,-1,sizeof(head));
        }
        void AddEdge(int u,int v,captype c,captype rc=0){
            edges[tot] = (Edge){u,v,head[u],c};  head[u]=tot++;
            edges[tot] = (Edge){v,u,head[v],rc}; head[v]=tot++;
        }
        captype maxFlow_sap(int sNode,int eNode, int n){//n是包括源点和汇点的总点个数,这个一定要注意
            memset(gap,0,sizeof(gap));
            memset(dis,0,sizeof(dis));
            memcpy(cur,head,sizeof(head));
            pre[sNode] = -1;
            gap[0]=n;
            captype ans=0;
            int u=sNode;
            while(dis[sNode]<n){
                if(u==eNode){
                    captype Min=INF ;
                    int inser;
                    for(int i=pre[u]; i!=-1; i=pre[edges[i^1].to])
                    if(Min>edges[i].cap){
                        Min=edges[i].cap;
                        inser=i;
                    }
                    for(int i=pre[u]; i!=-1; i=pre[edges[i^1].to]){
                        edges[i].cap-=Min;
                        edges[i^1].cap+=Min;
                    }
                    ans+=Min;
                    u=edges[inser^1].to;
                    continue;
                }
                bool flag = false;
                int v;
                for(int i=cur[u]; i!=-1; i=edges[i].next){
                    v=edges[i].to;
                    if(edges[i].cap>0 && dis[u]==dis[v]+1){
                        flag=true;
                        cur[u]=pre[v]=i;
                        break;
                    }
                }
                if(flag){
                    u=v;
                    continue;
                }
                int Mind= n;
                for(int i=head[u]; i!=-1; i=edges[i].next)
                if(edges[i].cap>0 && Mind>dis[edges[i].to]){
                    Mind=dis[edges[i].to];
                    cur[u]=i;
                }
                gap[dis[u]]--;
                if(gap[dis[u]]==0) return ans;
                dis[u]=Mind+1;
                gap[dis[u]]++;
                if(u!=sNode) u=edges[pre[u]^1].to;  //退一条边
            }
            return ans;
        }
    }F;
    
    int vis[MAXN];
    void dfs(int u)
    {
        vis[u] = 1;
        for(int i=F.head[u];~i;i=F.edges[i].next){
            int v= F.edges[i].to;
            if(!vis[v] && F.edges[i].cap>0){
                dfs(v);
            }
        }
    }
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        int N,M;
        int u,v,tmp;
        while(scanf("%d %d",&N, &M)==2){
            F.init();
            int s = 0,t = N*2+1;
            for(int i=1;i<=N;++i){
                scanf("%d",&tmp);
                F.AddEdge(i+N,t,tmp);
            }
            for(int i=1;i<=N;++i){
                scanf("%d",&tmp);
                F.AddEdge(s,i,tmp);
            }
            for(int i =1;i<=M;++i){
                scanf("%d %d",&u, &v);
                F.AddEdge(u,v+N,INF);
            }
            int flow = F.maxFlow_sap(s,t,t+1);
            memset(vis,0,sizeof(vis));
            dfs(s);
            vector<int> res;
            for(int i=F.head[s];~i;i=F.edges[i].next){
                int u = s;
                int v = F.edges[i].to;
                if(vis[u] && !vis[v]){
                    res.push_back(v);
                }
            }
            for(int i=F.head[t];~i;i=F.edges[i].next){
                int u = t;
                int v = F.edges[i].to;
                if(vis[v] && !vis[u]){
                    res.push_back(v);
                }
            }
            int sz = res.size();
            printf("%d
    %d
    ",flow,sz);
            for(int i=0;i<sz;++i){
                if(res[i]<=N){
                    printf("%d -",res[i]);
                }
                else{
                    printf("%d +",res[i]-N);
                }
                printf("
    ");
            }
        }
        return 0;
    }
    
    
    为了更好的明天
  • 相关阅读:
    Android开发总结
    LeakCanary原理分析
    机器学习
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):2. 实现绘图功能
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 3. 循环
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):1. 自定义窗口部件 (widget)
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 2. 变量
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 1. 神秘朋友
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 0. 准备工作
    远程显示(操作) 服务器 GUI 程序(图形化界面) (基于 X11 Forwarding + Centos + MobaXterm)
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9685069.html
Copyright © 2011-2022 走看看