zoukankan      html  css  js  c++  java
  • [BZOJ2561]最小生成树(最小割)

    [BZOJ2561]最小生成树(最小割)

    题面

    给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上?N ≤ 20000,M ≤ 200000,L ≤ 20000

    分析

    考虑Kruskal算法的过程,一条边((u,v,w))能被加入最小生成树,当且仅当加入所有权值(<w)的边之后,(u)(v)不连通。

    那么问题转化成删除最小的边,使得(u,v)不连通.直接建边权为1的边跑最小割即可,注意一条无向边要拆成两条。

    最大生成树同理,对(>w)的边操作即可,最后把两个答案累加起来。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #define INF 0x3f3f3f3f
    #define maxn 20000
    #define maxm 200000
    using namespace std;
    int n,m;
    int U,V,W;
    struct _edge{
        int from;
        int to;
        int len;
        friend bool operator < (_edge p,_edge q){
            return p.len<q.len;
        } 
    }G[maxm+5];
    
    
    namespace Dinic{
        struct edge{
            int from;
            int to;
            int next;
            int flow;
        }E[maxm*2+5];
        int head[maxn+5];
        int cur[maxn+5];
        int esz=1;
        void add_edge(int u,int v,int w){
        //	printf("%d->%d %d
    ",u,v,w); 
            esz++;
            E[esz].from=u;
            E[esz].to=v;
            E[esz].flow=w;
            E[esz].next=head[u];
            head[u]=esz;
            esz++;
            E[esz].from=v;
            E[esz].to=u;
            E[esz].flow=0;
            E[esz].next=head[v];
            head[v]=esz;
        }
        int deep[maxn+5];
        bool bfs(int s,int t){
            memset(deep,0,sizeof(deep));
            queue<int>q;
            q.push(s);
            deep[s]=1;
            while(!q.empty()){
                int x=q.front();
                q.pop();
                for(int i=head[x];i;i=E[i].next){
                    int y=E[i].to;
                    if(!deep[y]&&E[i].flow){
                        deep[y]=deep[x]+1;
                        q.push(y);
                        if(y==t) return 1;
                    }
                }
            }
            return 0;
        }
        int dfs(int x,int t,int minf){
            if(x==t) return minf;
            int rest=minf,k;
            for(int &i=cur[x];i;i=E[i].next){
                int y=E[i].to;
                if(E[i].flow&&deep[y]==deep[x]+1){
                    k=dfs(y,t,min(rest,E[i].flow));
                    E[i].flow-=k;
                    E[i^1].flow+=k;
                    rest-=k;
                    if(k==0) deep[y]=0;
                    if(rest==0) break; 
                }
            }
            return minf-rest;
        }
        int dinic(int s,int t){
            int ans=0;
            int now=0;
            while(bfs(s,t)){
                memcpy(cur,head,sizeof(head));
                while((now=dfs(s,t,INF))) ans+=now;
            } 
            return ans;
        }
        void clear(){
            esz=1;
            memset(head,0,sizeof(head));
        }
    }
    
    
    int main(){
    
        scanf("%d %d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d %d %d",&G[i].from,&G[i].to,&G[i].len);
        }	
        scanf("%d %d %d",&U,&V,&W);
        sort(G+1,G+1+m);
        int ans=0;
        for(int i=1;i<=m;i++){
            if(G[i].len<W){
                Dinic::add_edge(G[i].from,G[i].to,1);
                Dinic::add_edge(G[i].to,G[i].from,1);
            }
        }
        ans+=Dinic::dinic(U,V);
        Dinic::clear();
        for(int i=1;i<=m;i++){
            if(G[i].len>W){
                Dinic::add_edge(G[i].from,G[i].to,1);
                Dinic::add_edge(G[i].to,G[i].from,1);
            }
        }
        ans+=Dinic::dinic(U,V);
        printf("%d
    ",ans);
    
    } 
    
    
  • 相关阅读:
    Django使用xadmin集成富文本编辑器Ueditor(方法二)
    Django-xadmin后台配置富文本编辑器(方法一)
    求解函数不等式[给定具体函数]
    区间断想
    函数方程和函数不等式
    对函数的再理解
    多题一解
    破解函数性质中的表达难点
    [数学模型]应用举例
    函数的迭代
  • 原文地址:https://www.cnblogs.com/birchtree/p/13403600.html
Copyright © 2011-2022 走看看