zoukankan      html  css  js  c++  java
  • 【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点

    1797: [Ahoi2009]Mincut 最小割

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1685  Solved: 724
    [Submit][Status][Discuss]

    Description

    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 M1 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

    2015.4.16新加数据一组,可能会卡掉从前可以过的程序。

    Source

    Day1

    Solution

    首先,最小割-最大流定理,很显然想到最大流

    那么问题在于对于各个边是否选择的情况的判断

    考虑在求完最小割(最大流)的残余网络上进行处理,那么想到Tarjan+缩点

    讨论后发现,如下判断即可:

    对于问题1:

    如果一条边的左右端点不在同一SCC中,那么为1,否则为0

    对于问题2:

    满足一条边的左右端点必须一个端点与s同SCC,另一个端点与t同SCC,此时为1,否则为0

    当然还有一个特例,那就是这个边从未被割,那么很显然对于问题1和问题2同时为0

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    //quick read
    #define maxn 4000+100
    #define maxm (60000+100)*2
    struct data{int from,to,next,cap;}edge[maxm];
    int head[maxn],cnt=1,cur[maxn];
    void add(int u,int v,int w)
    {cnt++;edge[cnt].to=v;edge[cnt].from=u;
    edge[cnt].next=head[u];head[u]=cnt;edge[cnt].cap=w;}
    void insert(int u,int v,int w){add(u,v,w);add(v,u,0);}
    //add edge
    int n,m,s,t;int dis[maxn],q[maxn];
    bool bfs()
    {
        for (int i=1; i<=n; i++) dis[i]=-1;
        int he=0,ta=1; q[0]=s; dis[s]=0;
        while (he<ta)
            {
                int now=q[he++];
                for (int i=head[now]; i; i=edge[i].next)
                    if (dis[edge[i].to]==-1 && edge[i].cap)
                        dis[edge[i].to]=dis[now]+1,q[ta++]=edge[i].to;
            }
        return dis[t]!=-1;
    }
    int dfs(int loc,int low)
    {
        if (loc==t) return low;
        int w,used=0;
        for (int i=cur[loc]; i; i=edge[i].next)
            if (dis[edge[i].to]==dis[loc]+1)
                {
                    w=dfs(edge[i].to,min(low-used,edge[i].cap));
                    edge[i].cap-=w;edge[i^1].cap+=w;
                    if (edge[i].cap) cur[loc]=i;
                    used+=w; if (used==low) return low;    
                }
        if (!used) dis[loc]=-1;
        return used;
    }
    #define inf 0x7fffffff
    int dinic()
    {
        int tmp=0;
        while (bfs())
            {
                for (int i=1; i<=n; i++) cur[i]=head[i];
                tmp+=dfs(s,inf);
            }
        return tmp;
    }
    //MaxFlow Dinic
    int stack[maxn],st,qcnt,tot;
    int dfn[maxn],loww[maxn],belong[maxn],num[maxn];bool visit[maxn];
    void Tarjan(int x)
    {
        dfn[x]=loww[x]=++tot; stack[++st]=x; visit[x]=1; 
        for (int i=head[x]; i; i=edge[i].next)
            if (edge[i].cap)//根据题意,在Tarjan的时候需要进行此判断,否则会出问题
                {
                    if (!dfn[edge[i].to])
                           {
                            Tarjan(edge[i].to);
                            if (loww[edge[i].to]<loww[x]) loww[x]=loww[edge[i].to];
                        }
                    else if(visit[edge[i].to] && dfn[edge[i].to]<loww[x])
                            loww[x]=dfn[edge[i].to];
                }
        if (dfn[x]==loww[x])
            {
                qcnt++;int u;
                while (x!=u)
                    u=stack[st--],num[qcnt]++,
                    visit[u]=0,belong[u]=qcnt; 
            }
    }
    //Tarjan SCC
    int main()
    {
        n=read(),m=read(),s=read(),t=read();
        for (int u,v,c,i=1; i<=m; i++)
            u=read(),v=read(),c=read(),insert(u,v,c);
        int maxflow=dinic();
        for (int i=1; i<=n; i++)
            if (!dfn[i]) Tarjan(i);
        for (int ans1,ans2,u,v,i=2; i<=cnt; i+=2)
            {
                u=edge[i].from,v=edge[i].to;
                if (edge[i].cap) ans1=0,ans2=0;
                    else 
                        {
                            if (belong[u]!=belong[v]) 
                                ans1=1; else ans1=0;
                            if (belong[u]==belong[s] && belong[v]==belong[t])
                                ans2=1; else ans2=0;
                        }
                printf("%d %d
    ",ans1,ans2);
            }
        return 0;
    }

    本来应该做的飞快,然而...自己脑残打错两个变量...坑了好久....SB错误毁一生啊!!

  • 相关阅读:
    Django之forms.Form
    Django之Middleware中间件方法使用
    Django之请求生命周期
    Django操作session实例
    Django操作cookie实例
    Django操作session
    Django操作cookie
    Django之cookie与session
    Django之AJAX传输JSON数据
    Django之JSON数据格式
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5353017.html
Copyright © 2011-2022 走看看