zoukankan      html  css  js  c++  java
  • bzoj2561: 最小生成树(最小割)

    https://www.lydsy.com/JudgeOnline/problem.php?id=2561

    考虑Kruscal算法求最小生成树的流程

    如果 u和v之间的长为L的边能出现在最小生成树里,说明<L的边不能时u和v联通

    即求图中只存在<L的边时,u和v的最小割

    如果 u和v之间的长为L的边能出现在最大生成树里,说明>L的边不能时u和v联通

    即求图中只存在>L的边时,u和v的最小割

    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
     
    using namespace std;
     
    #define N 20001
    #define M 200001
     
    int n,m;
     
    int tot;
    int src,decc;
    int front[N],to[M<<1],nxt[M<<1],cap[M<<1];
     
    int lev[N],cur[N];
    queue<int>q;
     
    struct node
    {
        int u,v,l;
    }e[M];
     
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
     
    bool bfs()
    {
            for(int i=0;i<=n;++i) cur[i]=front[i],lev[i]=-1;
            while(!q.empty()) q.pop();
            q.push(src);
            lev[src]=0;
            int now,t;
            while(!q.empty())
            {
                now=q.front();
                q.pop();
                for(int i=front[now];i;i=nxt[i])
                {
                    t=to[i];
                    if(lev[t]==-1 && cap[i])
                    {
                        lev[t]=lev[now]+1;
                        if(t==decc) return true;
                        q.push(t);
                    }
                }
            }
            return false;
    }
     
    int dinic(int now,int flow)
    {
            if(now==decc) return flow;
            int rest=0,delta;
            for(int &i=cur[now];i;i=nxt[i])
            if(cap[i] && lev[to[i]]==lev[now]+1)
            {
                delta=dinic(to[i],min(flow-rest,cap[i]));
                if(delta)
                {
                    rest+=delta; 
                    cap[i]-=delta; cap[i^1]+=delta;
                    if(rest==flow) break;
                }
            }
            if(rest!=flow) lev[now]=-1;
            return rest;
    }
     
    bool cmp1(node p,node q)
    {
        return p.l<q.l;
    }
     
    bool cmp2(node p,node q)
    {
        return p.l>q.l;
    }
     
    void add(int u,int v,int w)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; cap[tot]=w;
    }
     
    int main()
    {
        read(n); read(m);
        for(int i=1;i<=m;++i) read(e[i].u),read(e[i].v),read(e[i].l);    
        read(src); read(decc);
        int L;
        read(L);
        int ans=0;
        tot=1;
        sort(e+1,e+m+1,cmp1);
        for(int i=1;i<=m;++i)
            if(e[i].l>=L) break;
            else add(e[i].u,e[i].v,1);
        while(bfs()) ans+=dinic(src,2e9);
        memset(front,0,sizeof(front));
        tot=1;
        sort(e+1,e+m+1,cmp2);
        for(int i=1;i<=m;++i)
            if(e[i].l<=L) break;
            else add(e[i].u,e[i].v,1);
        while(bfs()) ans+=dinic(src,2e9);
        printf("%d",ans);
    }
  • 相关阅读:
    iOS使用技能
    iOS 视频播放的简单使用
    iOS中二维码的生成与使用(入门篇)
    正则表达式的小总结
    最近项目中巧遇的几个好工具,分享一下
    Foundation与coreFoundation的相互转换
    iOS实用技能扩展-集成支付宝
    iOS实用技能扩展-静态库的制作与简单使用
    数据存储的三种方式
    Magento获取IP地址
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8991620.html
Copyright © 2011-2022 走看看