zoukankan      html  css  js  c++  java
  • 【BZOJ】2561: 最小生成树【网络流】【最小割】

    2561: 最小生成树
    Time Limit: 10 Sec Memory Limit: 128 MB
    Submit: 2685 Solved: 1253
    [Submit][Status][Discuss]
    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
     输出一行一个整数表示最少需要删掉的边的数量。

    Sample Input
    3 2
    3 2 1
    1 2 3
    1 2 2
    Sample Output
    1

    HINT

    对于20%的数据满足N ≤ 10,M ≤ 20,L ≤ 20;

    对于50%的数据满足N ≤ 300,M ≤ 3000,L ≤ 200;

    对于100%的数据满足N ≤ 20000,M ≤ 200000,L ≤ 20000。

    Solution

    完全看不出是网络流QAQ.....

    很神奇的想法...

    要使加的边在最小生成树上,就要使原图中所有能连接u,v的边并且长度小于L的通路被切断,最大生成树同理。

    所以就是以u,v为源汇点跑最小割。重新建边。

    为什么可以建双向边?因为这道题没确定方向,所以双向边是必要的。而在bfs中从源点出发更新其他点的dep,相当于是确定了方向,所以双向边也可以跑最小割了。

    #include<bits/stdc++.h>
    using namespace std;
    inline void read(int &x) {
        x = 0; char ch = getchar();
        while(ch > '9' || ch < '0')    ch = getchar();
        while(ch >= '0' && ch <= '9') {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
    }
    struct Node {
        int u, v, f, nex;
        Node(int u = 0, int v = 0, int nex = 0, int f = 0) :
            u(u), v(v), nex(nex), f(f) { }
    } Edge[4000005];
    struct Init {
        int u, v, w;
    } a[200005];
    int stot = 1, h[20005];
    void add(int u, int v, int f) {
        Edge[++stot] = Node(u, v, h[u], f);
        h[u] = stot;
        Edge[++stot] = Node(v, u, h[v], 0);
        h[v] = stot;
    }
    int n, m, s, t, w;
    int vis[20005], dep[20005];
    bool bfs() {
        memset(vis, 0, sizeof(vis));
        memset(dep, 0, sizeof(dep));
        queue < int > q;
        q.push(s); vis[s] = 1;
        while(!q.empty()) {
            int u = q.front(); q.pop();
            for(int i = h[u]; i; i = Edge[i].nex) {
                int v = Edge[i].v;
                if(!vis[v] && Edge[i].f) {
                    dep[v] = dep[u] + 1;
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
        return vis[t];
    }
    int dfs(int u, int delta) {
        if(u == t || !delta)    return delta;
        int res = 0;
        for(int i = h[u]; i && delta; i = Edge[i].nex) {
            int v = Edge[i].v;
            if(dep[v] == dep[u] + 1 && Edge[i].f) {
                int dd = dfs(v, min(delta, Edge[i].f));
                Edge[i].f -= dd;
                Edge[i ^ 1].f += dd;
                res += dd;    delta -= dd;
            }
        }
        return res;
    }
    int main() {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; i ++)
            read(a[i].u), read(a[i].v), read(a[i].w);
        read(s), read(t), read(w);
        for(int i = 1; i <= m; i ++)
            if(a[i].w < w)    add(a[i].u, a[i].v, 1),    add(a[i].v, a[i].u, 1);
        int t1 = 0, t2 = 0;
        while(bfs())    t1 += dfs(s, 0x3f3f3f3f);
        stot = 1; memset(h, 0, sizeof(h));
        for(int i = 1; i <= m; i ++)
            if(a[i].w > w)    add(a[i].u, a[i].v, 1),    add(a[i].v, a[i].u, 1);
        while(bfs())    t2 += dfs(s, 0x3f3f3f3f);
        printf("%d", t1 + t2);
        return 0;
    }
    
  • 相关阅读:
    NOIP1998提高组——挖地雷
    模板——EXBSGS
    vue 知识点
    jq_js
    ruby 基础知识(一)
    idea maven pom配置文件
    .net core dapper (5)
    .net core dapper (4)
    .net core dapper (3)
    .net core dapper (2)
  • 原文地址:https://www.cnblogs.com/NoTimepleasssse/p/9826486.html
Copyright © 2011-2022 走看看