zoukankan      html  css  js  c++  java
  • HYSBZ 1797 Mincut 最小割

    Descrption

    A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路。设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci。现在B国想找出一个路径切断方案,使中转站s不能到达中转站t,并且切断路径的代价之和最小。 小可可一眼就看出,这是一个求最小割的问题。但爱思考的小可可并不局限于此。现在他对每条单向道路提出两个问题: 问题一:是否存在一个最小代价路径切断方案,其中该道路被切断? 问题二:是否对任何一个最小代价路径切断方案,都有该道路被切断? 现在请你回答这两个问题。

    Input

    第一行有4个正整数,依次为N,M,s和t。第2行到第(M+1)行每行3个正 整数v,u,c表示v中转站到u中转站之间有单向道路相连,单向道路的起点是v, 终点是u,切断它的代价是c(1≤c≤100000)。 注意:两个中转站之间可能有多条道路直接相连。 同一行相邻两数之间可能有一个或多个空格。

    Output

    对每条单向边,按输入顺序,依次输出一行,包含两个非0即1的整数,分 别表示对问题一和问题二的回答(其中输出1表示是,输出0表示否)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

    Sample Input

    6 7 1 6
    1 2 3
    1 3 2
    2 4 4
    2 5 1
    3 5 5
    4 6 2
    5 6 3

    Sample Output

    1 0
    1 0
    0 0
    1 0
    0 0
    1 0
    1 0

    Hint

    设第(i+1)行输入的边为i号边,那么{1,2},{6,7},{2,4,6}是仅有的三个最小代价切割方案。它们的并是{1,2,4,6,7},交是 。 【数据规模和约定】 测试数据规模如下表所示 数据编号 N M 数据编号 N M 1 10 50 6 1000 20000 2 20 200 7 1000 40000 3 200 2000 8 2000 50000 4 200 2000 9 3000 60000 5 1000 20000 10 4000 60000

     题目分析

    题意:给出一个图,求最小割,随后问图中每一条边是否满足这两个判断:1)该道路是否是某一最小割集中的边,2)该道路是否是所有的最小割集中的边;对于每一条边,输出这个判断的结果。

    思路:先跑一遍Dinic,求出最小割,随后用tarjan算法在残余网络中求出所有的强连通分量,用node[i]表示点i所在强连通分量的编号,由于残余网络中没有s-t的通路,因此肯定有 node[s] != node[t],对于两个判断的处理入下:

    1)我们将每个残余网络缩成点,如果某个边是满流边,并且边的两端点分属于不同的强连通分量,那么这条边一定是某最小割集中的边

    2)如果某条边的两端点分别是 s和 t 所在强连通分量node[s],node[t]中的点,那么这条边为所有割集中包含的边

    (博主比较弱,无法具体证明的话,只能直接用结论了)

    代码区

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<string>
    #include<fstream>
    #include<vector>
    #include<stack>
    #include <map>
    #include <iomanip>
    
    #define bug cout << "**********" << endl
    #define show(x, y) cout<<"["<<x<<","<<y<<"] "
    #define LOCAL = 1;
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    const ll mod = 1e9 + 7;
    const int Max = 1e5 + 10;
    
    struct Edge
    {
        int from, to, next, flow;
    } edge[Max << 1];
    
    int n, m, s, t;
    int head[Max], tot;
    int dis[Max];
    int dfn[Max], low[Max], time_clock;
    int node[Max], ans;
    int line[Max], now;
    
    void init()
    {
        memset(head, -1, sizeof(head));
        tot = 0;
        memset(node, 0, sizeof(node));
        memset(dfn,0,sizeof(dfn));time_clock = 0;
        now = 0;ans = 0;
    }
    
    void add(int u, int v, int flow)
    {
        edge[tot].from = u;
        edge[tot].to = v;
        edge[tot].flow = flow;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    
    bool bfs()
    {
        memset(dis, -1, sizeof(dis));
        queue<int> q;
        q.push(s);
        dis[s] = 0;
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            for (int i = head[u]; i != -1; i = edge[i].next)
            {
                int v = edge[i].to;
                if (edge[i].flow > 0 && dis[v] == -1)
                {
                    dis[v] = dis[u] + 1;
                    if (v == t)
                        return true;
                    q.push(v);
                }
            }
        }
        return false;
    }
    
    int dfs(int u, int flow_in)
    {
        if (u == t)
            return flow_in;
        int flow_out = 0;
        for (int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if (dis[v] == dis[u] + 1 && edge[i].flow > 0)
            {
                int flow = dfs(v, min(flow_in, edge[i].flow));
                if (flow == 0)
                    continue;
                flow_in -= flow;
                flow_out += flow;
                edge[i].flow -= flow;
                edge[i^1].flow += flow;
                if (flow_in == 0)
                    break;
            }
        }
        return flow_out;
    }
    
    int Dinic()
    {
        int sum = 0;
        while (bfs())
        {
            sum += dfs(s, inf);
        }
        return sum;
    }
    
    void tarjan(int u)
    {
        dfn[u] = low[u] = ++time_clock;
        line[++now] = u;
        for(int i = head[u] ;i != -1 ;i = edge[i].next)
        {
            int v = edge[i].to;
            if(edge[i].flow > 0)
            {
                if(!dfn[v])
                {
                    tarjan(v);
                    low[u] =  min(low[u],low[v]);
                }
                else if(!node[v])
                {
                    low[u] = min(low[u],dfn[v]);
                }
            }
        }
        if(dfn[u] == low[u])
        {
            ans++;
            while(line[now] != u)
            {
                node[line[now--]] = ans;
            }
            node[line[now--]] = ans;
        }
    }
    
    int main()
    {
    #ifdef LOCAL
        //freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
    #endif
        while(scanf("%d%d%d%d",&n,&m,&s,&t)!=EOF)
        {
            init();
            for(int i = 1, u, v, flow ;i <= m ;i++)
            {
                scanf("%d%d%d",&u,&v,&flow);
                add(u,v,flow);add(v,u,0);
            }
            Dinic();
            for(int i = 1 ;i <= n ;i ++)
                if(!dfn[i]) tarjan(i);
    
            for(int i = 0 ;i < tot ; i += 2)
            {
                if(edge[i].flow) printf("0 0
    ");
                else
                {
                    if(node[edge[i].from] != node[edge[i].to])
                        printf("1 ");
                    else
                        printf("0 ");
    
                    if(node[edge[i].from] == node[s] && node[edge[i].to] == node[t])
                        printf("1
    ");
                    else
                        printf("0
    ");
                }
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    LeetCode:12. Roman to Integer (Easy)
    Python:正则表达式—— re 模块
    RAID(冗余硬盘阵列)
    Mac OS下搭建Hadoop + Spark集群
    LeetCode:12. Integer to Roman(Medium)
    js事件中绑定另一事件导致事件多次执行
    ie8以上及非ie8情况下的写法
    javascript闭包
    bootstrap-datetimepicker年视图中endDate设置之后比正常时间提前两个月
    javascript的阻塞机制
  • 原文地址:https://www.cnblogs.com/winter-bamboo/p/11366123.html
Copyright © 2011-2022 走看看