zoukankan      html  css  js  c++  java
  • bzoj2561-最小生成树

    题目

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

    分析

    一开始是从最小生成树的Kruskal想,想到了先求两次最小生成树再用优先级求两次最大生成树,后来发现是错的。正解网络流。 若一条边可以出现在最小生成树上,那么就说明比它小的边不能把这两个点联通,最大生成树同理。问题转化成了求比这条边小的边中去掉多少个不联通,于是可以想到用每条边流量为1的最小割。对比(w)小和大分别求两次,加起来就是答案。

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #include<queue>
    #define F(x) for (int i=h[x],v=e[i].v,w=e[i].w;~i;i=e[i].nxt,v=e[i].v,w=e[i].w)
    using namespace std;
    int read() {
        int x=0,f=1;
        char c=getchar();
        for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
        for (;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=2e4+10;
    const int maxm=2e5+10;
    const int inf=1e9+10;
    struct gp {
        int u,v,w;
    } a[maxm];
    struct edge {
        int v,w,nxt;
    } e[maxm<<2];
    int h[maxn],tot=0,nowinf;
    void add(int u,int v,int w) {
        e[tot]=(edge){v,w,h[u]};
        h[u]=tot++;
    }
    void adde(int u,int v,int w) {
        add(u,v,w),add(v,u,0);
    }
    int dis[maxn];
    queue<int> q;
    bool bfs(int s,int t) {
        q.push(s);
        memset(dis,0x3f,sizeof dis);
        nowinf=dis[0];
        dis[s]=0;
        while (!q.empty()) {
            int u=q.front();
            q.pop();
            F(u) if (w>0 && dis[v]==nowinf) {
                dis[v]=dis[u]+1;
                q.push(v);
            }
        }
        return dis[t]!=nowinf;
    }
    int Flow(int x,int t,int mi) {
        if (x==t) return mi;
        int tmp=0;
        F(x) if (w>0 && dis[v]==dis[x]+1) {
            int now=Flow(v,t,min(mi,w));
            mi-=now;
            e[i].w-=now;
            e[i^1].w+=now;
            tmp+=now;
            if (mi==0) break;
        }
        if (!tmp) dis[x]=-1;
        return tmp;
    }
    int maxflow(int s,int t) {
        int ret=0;
        while (bfs(s,t)) {
            ret+=Flow(s,t,inf);
        }
        return ret;
    }
    int main() {
        #ifndef ONLINE_JUDGE
            freopen("test.in","r",stdin);
        #endif
        int n=read(),m=read();
        for (int i=1;i<=m;++i) a[i].u=read(),a[i].v=read(),a[i].w=read();
        int s=read(),t=read(),w=read();
        memset(h,0xff,sizeof h),tot=0;
        for (int i=1;i<=m;++i) if (a[i].w<w) adde(a[i].u,a[i].v,1),adde(a[i].v,a[i].u,1); 
        int fa=maxflow(s,t);
        memset(h,0xff,sizeof h),tot=0;
        for (int i=1;i<=m;++i) if (a[i].w>w) adde(a[i].u,a[i].v,1),adde(a[i].v,a[i].u,1);
        int fb=maxflow(s,t);
        int ans=fa+fb;
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    Node.js核心模块-net
    ie8兼容rgba写法
    Node.js核心模块-http
    Node.js核心模块-fs文件系统
    js监听滚动结束
    mac本地安装全局包报错npm WARN checkPermissions
    安全测试回顾(一)
    python学习笔记(二):python数据类型
    python学习笔记(一):python简介和入门
    Centos下安装Redis
  • 原文地址:https://www.cnblogs.com/owenyu/p/6724587.html
Copyright © 2011-2022 走看看