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;
    }
    
    
    为了更好的明天
  • 相关阅读:
    解决iOS app集成共享QQ场地,微信的朋友,朋友等功能圈,不能采用苹果公司的审计问题
    沙朗新闻发布系统汇总
    Cocos2d-x示例:单点触摸事件
    【UVA272】TEX Quotes
    Android多线程的研究(8)——Java5于Futrue获取线程返回结果
    Spring Assert主张 (参议院检测工具的方法-主张)
    redmine使用汇总redmine软件工程过程
    IIS7构造Gzip压缩
    PHPthinking官方论坛
    javaweb学习总结(十一)——使用Cookie进行会话管理
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9685069.html
Copyright © 2011-2022 走看看