zoukankan      html  css  js  c++  java
  • BZOJ2561 最小生成树(Dinic算法求最小割)

    Description

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

     

    Input

     第一行包含用空格隔开的两个整数,分别为N和M;   接下来M行,每行包含三个正整数u,v和w表示图G存在一条边权为w的边(u,v)。   最后一行包含用空格隔开的三个整数,分别为u,v,和 L;   数据保证图中没有自环。

     

    Output

     输出一行一个整数表示最少需要删掉的边的数量。

     

    题解:

    将所有比L小的边连一条边,计算最小割

    重新建图,将所有比L大的边连一条边,计算最小割

    两个值加起来就是答案。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    const int inf=1e9;
    int N,M;
    struct node {
        int u;
        int v;
        int w;
        int next;
    }edge[maxn];
    int head[maxn];
    int tol=0;
    void addedge (int u,int v,int w) {
        edge[tol].u=u;
        edge[tol].v=v;
        edge[tol].w=w;
        edge[tol].next=head[u];
        head[u]=tol++;
    }
    
    
    int dep[maxn];
    int inque[maxn];
    int vi;
    int cur[maxn];
    int maxflow=0;
    int s,t;
    void init () {
       maxflow=0;
       vi=0;
       tol=0;
       memset(head,-1,sizeof(head));
    }
    bool bfs () {
        for (int i=1;i<=N;i++) 
            cur[i]=head[i],dep[i]=inf,inque[i]=0;
        dep[s]=0;
        queue<int> q;
        q.push(s);
        while (!q.empty()) {
            int u=q.front();
            q.pop();
            inque[u]=0;
            for (int i=head[u];i!=-1;i=edge[i].next) {
                int v=edge[i].v;
                if (dep[v]>dep[u]+1&&edge[i].w) {
                    dep[v]=dep[u]+1;
                    if (inque[v]==0) {
                        q.push(v);
                        inque[v]=1;
                    }
                }
            }
        } 
        if (dep[t]!=inf) return 1;
        return 0;
    }
    
    int dfs (int u,int flow) {
        int increase=0;
        if (u==t) {
            vi=1;
            maxflow+=flow;
            return flow;
        }
        int used=0;
        for (int i=cur[u];i!=-1;i=edge[i].next) {
            cur[u]=i;
            int v=edge[i].v;
            if (edge[i].w&&dep[v]==dep[u]+1) {
                if (increase=dfs(v,min(flow-used,edge[i].w))) {
                    used+=increase;
                    edge[i].w-=increase;
                    edge[i^1].w+=increase;
                    if (used==flow) break;
                }
            }
        }
        return used;
    }
    int Dinic () {
        while (bfs()) {
            vi=1;
            while (vi==1) {
                vi=0;
                dfs(s,inf);
            }
        }
        return maxflow;
    }
    int a[maxn],b[maxn],c[maxn];
    int main () {
        scanf("%d%d",&N,&M);
        for (int i=1;i<=M;i++) {
            scanf("%d%d%d",&a[i],&b[i],&c[i]);
        }
        int U,V,L;
        scanf("%d%d%d",&U,&V,&L);
        s=U;
        t=V;
        init();
        int ans=0;
        for (int i=1;i<=M;i++) 
            if (c[i]<L) {
                addedge(a[i],b[i],1);
                addedge(b[i],a[i],1);
            }
        ans+=Dinic();
        init();
        for (int i=1;i<=M;i++) 
            if (c[i]>L) {
                addedge(a[i],b[i],1);
                addedge(b[i],a[i],1);
            }
        ans+=Dinic();
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Atitit flowable使用总结 目录 1. flowable 1 1.1. 添加依赖 1 1.2. Flowable的启动接口 2 2. 还是使用简单流程来完成业务流程的学习, 2 2.1.
    dell xps15 9550安装黑苹果
    显示器色域
    数据标准化的方法与意义
    XPS9550困扰我的散热问题终于解决了
    app开发
    纹理
    用 Java 开发一个打飞机小游戏(附完整源码)
    Spring Cloud Gateway 限流实战,终于有人写清楚了!
    OracleJDK 和 OpenJDK 有什么区别?来看看大神的回答!
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12509272.html
Copyright © 2011-2022 走看看