[BZOJ2095][Poi2010]Bridges (Binary+Maximum Flow+Euler diagram)

Posted by stitchmedia on Tue, 09 Jul 2019 19:31:22 +0200

Title Description

Portal

Main idea of the topic: An undirected graph with n points and m edges, each edge has different values for forward and reverse walking.Find an Euler circuit in the diagram, and the maximum value to go is the smallest.

Problem

It's easy to think of a dichotomous answer, the key is how to decide
There are two conditions for judging Euler circuit:1. Strong connectivity of the whole graph and 2. Degree of entry = Degree of exit for each point
First, if one of the edges in the graph is broken, then there is no solution.
Then there are some directed edges and some undirected edges, which is a mixed graph Euler Circuit decision problem
Firstly, each undirected edge is arbitrarily given a direction, and the weight d(i) =exit-entry for each point is obtained. If D of a point is odd, there is no solution.
Then build a network flow diagram, which first preserves all undirected edges in the original diagram with a capacity of 1
For each point i, if d(i)>0, then the contiguous s->i, d(i)/2, and if d(i)<0, then the contiguous i->t, -d(i)/2
Then run the maximum flow on this network flow graph. If the edges from s are full, then there is a solution, otherwise there is no solution.
If the full flow has a solution, it means that the directed edges of the full flow in the network flow diagram are all reversed in the original diagram, and there is a Euler loop.Since the capacity of the edge is d(i)/2, which is equivalent to turning half of the entrance into an exit, the final Exit-Entry of each point is exactly 0
However, the more obscure point of this question is that it ensures the strong connectivity of the graph, and in the case of incomplete edges, the whole graph must also be strong connectivity if the degree of outreach = degree of entry of each point is satisfied, so it is not necessary to judge this.

Code

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
#define N 1010
#define E 20010
#define inf 1000000000

int n,m,Max,scc,top,dfs_clock,s,t,maxflow,ans;
struct data{int x,y,a,b;}e[E];
int tot,point[N],nxt[E],v[E],remain[E];
int in[N],out[N],deep[N],last[N],cur[N],num[N];
queue <int> q;

void addedge(int x,int y,int cap)
{
    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap;
    ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
void bfs(int t)
{
    for (int i=1;i<=t;++i) deep[i]=t;
    deep[t]=0;
    for (int i=1;i<=t;++i) cur[i]=point[i];
    q.push(t);
    while (!q.empty())
    {
        int now=q.front();q.pop();
        for (int i=point[now];i!=-1;i=nxt[i])
            if (deep[v[i]]==t&&remain[i^1])
            {
                deep[v[i]]=deep[now]+1;
                q.push(v[i]);
            }
    }
}
int addflow(int s,int t)
{
    int now=t,ans=inf;
    while (now!=s)
    {
        ans=min(ans,remain[last[now]]);
        now=v[last[now]^1];
    }
    now=t;
    while (now!=s)
    {
        remain[last[now]]-=ans;
        remain[last[now]^1]+=ans;
        now=v[last[now]^1];
    }
    return ans;
}
void isap(int s,int t)
{
    bfs(t);
    for (int i=1;i<=t;++i) ++num[deep[i]];

    int now=s;
    while (deep[s]<t)
    {
        if (now==t)
        {
            maxflow+=addflow(s,t);
            now=s;
        }
        bool has_find=0;
        for (int i=cur[now];i!=-1;i=nxt[i])
        {
            cur[now]=i;
            if (deep[v[i]]+1==deep[now]&&remain[i])
            {
                has_find=1;
                last[v[i]]=i;
                now=v[i];
                break;
            }
        }
        if (!has_find)
        {
            int minn=t-1;
            for (int i=point[now];i!=-1;i=nxt[i])
                if (remain[i]) minn=min(minn,deep[v[i]]);
            if (!(--num[deep[now]])) break;
            ++num[deep[now]=minn+1];
            cur[now]=point[now];
            if (now!=s) now=v[last[now]^1];
        }
    }
}
bool check(int mid)
{
    tot=-1;memset(point,-1,sizeof(point));
    memset(num,0,sizeof(num));
    memset(in,0,sizeof(in));memset(out,0,sizeof(out));
    s=n+1,t=s+1;
    for (int i=1;i<=m;++i)
    {
        if (e[i].a>mid&&e[i].b>mid) return 0;
        if (e[i].a<=mid&&e[i].b<=mid)
            addedge(e[i].x,e[i].y,1),++out[e[i].x],++in[e[i].y];
        else
        {
            if (e[i].a<=mid) ++out[e[i].x],++in[e[i].y];
            else if (e[i].b<=mid) ++in[e[i].x],++out[e[i].y];
        }
    }
    int sum=0;
    for (int i=1;i<=n;++i)
    {
        int d=out[i]-in[i];
        if (d&1) return 0;
        if (d>0) addedge(s,i,d/2),sum+=d/2;
        if (d<0) addedge(i,t,-d/2);
    }
    maxflow=0;isap(s,t);
    return sum==maxflow;
}
int find()
{
    int l=1,r=Max,mid,ans=-1;
    while (l<=r)
    {
        mid=(l+r)>>1;
        if (check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;++i)
    {
        scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].a,&e[i].b);
        Max=max(Max,e[i].a);Max=max(Max,e[i].b);
    }
    ans=find();
    if (ans==-1) puts("NIE");
    else printf("%d\n",ans);
}

Topics: network