Bzoj1797 ahoi2009最小割

誒我擦今天早晨起晚了。。。。


這個題是昨天睡前過的。。


這個題要求兩個東西

一個是最小割的可行邊,一個是必須邊


可行邊:有可能在最小割中的邊

必須邊:一定在最小割中的邊


那麼首先要求一次最小割是肯定的

然後首先考慮求出可行邊:如果對於一條邊,他的兩個端點在殘餘網絡中可以互相達到那麼這個一定不是答案,但是如果每次詢問都一次dfs顯然太慢了,所以我們可以利用tarjan求出強連通分量,如果一個邊的兩個點在不同的強聯通分量中那麼這就是可行邊


最後考慮必須邊,這個邊的左端點一定和s是聯通的,右端點一定和t是聯通的,所以只需要判斷一下就可以了

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<stack>
#define maxm 60009
#define maxn 60009
#define inf 0x7fffffff/2
#define rep(i,j,k) for(int i=j;i<=k;i++)
 
using namespace std;
 
int tot=1,n,m,next[2*maxm],head[maxn],value[2*maxm],flow[2*maxm],done[maxn];
int to[2*maxm],ask[maxm][3],ans[maxm][2],dis[maxn],in[maxn];
int dfn[maxn],low[maxn],dfs_clock=0,scc_num=0,scc[maxn],s,t,MaxFlow=0;
 
stack<int>S;
 
void add(int From,int To,int weight)
{
    to[++tot]=To;
    next[tot]=head[From];
    head[From]=tot;
    value[tot]=flow[tot]=weight;
 
    to[++tot]=From;
    next[tot]=head[To];
    value[tot]=flow[tot]=0;
    head[To]=tot;
}
 
bool bfs()
{
    memset(done,0,sizeof(done));
    queue<int>q;
    done[s]=1;
    dis[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(int i=head[now];i;i=next[i])
            if(!done[to[i]]&&flow[i]>0)
                done[to[i]]=1,dis[to[i]]=dis[now]+1,q.push(to[i]);
    }
    return done[t];
}
 
int dfs(int x,int a)
{
    if(x==t||!a)
        return a;
    int f,Return=0;
    for(int i=head[x];i;i=next[i])
    {
        int y=to[i];
        if(dis[y]==dis[x]+1&&(f=dfs(y,min(a,flow[i])))>0)
        {
            flow[i]-=f,flow[i^1]+=f,Return+=f,a-=f;
            if(!a)
                return Return;
        }
    }
    return Return;
}
 
void tarjan(int x)
{
    in[x]=1;
    dfn[x]=low[x]=++dfs_clock;
    S.push(x);
    for(int i=head[x];i;i=next[i])
        if(flow[i]>0)
        {
            if(!dfn[to[i]])
            {
                tarjan(to[i]);
                low[x]=min(low[x],low[to[i]]);
            }
            else
                if(in[to[i]])
                    low[x]=min(low[x],dfn[to[i]]);
        }
 
    if(dfn[x]==low[x])
    {
        scc_num++;
        while(!S.empty())
        {
            int now=S.top();
            S.pop();
            scc[now]=scc_num;
            in[now]=0;
            if(now==x)
                break;
        }
    }
    return;
}
 
int main()
{
    scanf("%d%d%d %d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&ask[i][0],&ask[i][1],&ask[i][2]),add(ask[i][0],ask[i][1],ask[i][2]);
 
    while(bfs())
        MaxFlow+=dfs(s,inf);
     
    memset(scc,0,sizeof(scc));
    rep(i,1,n)
        if(!dfn[i])
            tarjan(i);
 
    for(int i=2;i<=tot;i+=2)
    {
        if(!flow[i]&&scc[to[i]]!=scc[to[i^1]])
            printf("1");
        else
            printf("0");
        if(!flow[i]&&scc[to[i^1]]==scc[s]&&scc[to[i]]==scc[t])
            printf(" 1\n");
        else
            printf(" 0\n");
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章