Bzoj2095:[Poi2010]Bridges:混合图欧拉回路,网络流

来源:互联网 发布:常用电脑软件 编辑:程序博客网 时间:2024/05/22 10:47

题目链接:2095:[Poi2010]Bridges

二分答案建图后显然是混合图的欧拉回路,有向边删掉无向边随机定向计算入度-出度的差du[i],如果du[i]<0连边(i,T,-du[i]/2),否则连边(S,i,du[i]/2)并计算du[i]/2的和num,跑一边最大流答案如果等于num则此时存在回路

#include<queue>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=100010;const int inf=0x7fffffff/3;int n,m,tot,h[maxn],vis[maxn],S,T;struct edge{int to,next,w;}G[maxn*2];struct edges{int a,b,c,d;}e[maxn*2];int cur[maxn],du[maxn],mx=0;int num=0,mn=inf;void add(int x,int y,int z){    G[++tot].to=y;G[tot].next=h[x];h[x]=tot;G[tot].w=z;    G[++tot].to=x;G[tot].next=h[y];h[y]=tot;G[tot].w=0;}bool bfs(){    for (int i=S;i<=T;++i) vis[i]=-1;    queue<int>q; q.push(S); vis[S]=0;    while (!q.empty()){        int u=q.front(); q.pop();        for (int i=h[u];i;i=G[i].next){            int v=G[i].to;            if (vis[v]==-1&&G[i].w){                vis[v]=vis[u]+1;                q.push(v);            }        }    }return vis[T]!=-1;}int dfs(int x,int f){    if (x==T||f==0) return f;    int w,used=0;    for (int i=cur[x];i;i=G[i].next)        if (G[i].w&&vis[G[i].to]==vis[x]+1){            w=f-used;            w=dfs(G[i].to,min(w,G[i].w));            G[i].w-=w; G[i^1].w+=w;            if (G[i].w) cur[x]=i;            used+=w; if (used==f) return f;        }    if (!used) vis[x]=-1;    return used;}void rebuild(int x){    memset(h,0,sizeof(h)); tot=1;    memset(du,0,sizeof(du)); num=0;    for (int i=1;i<=m;++i){        if (e[i].c<=x) du[e[i].a]--,du[e[i].b]++;        if (e[i].d<=x) add(e[i].b,e[i].a,1);    }    for (int i=1;i<=n;++i)        if (du[i]>0) num+=du[i]/2,add(S,i,du[i]/2);        else if (du[i]<0) add(i,T,-du[i]/2);}bool check(int x){    rebuild(x); int ret=0;for (int i=1;i<=n;++i) if (du[i]&1) return 0;    while (bfs()){        for (int i=S;i<=T;++i) cur[i]=h[i];        ret+=dfs(S,inf);    }if (ret==num) return 1;    else return 0;}int main(){    scanf("%d%d",&n,&m);    S=0; T=n+1;    for (int i=1;i<=m;++i){        scanf("%d%d%d%d",&e[i].a,&e[i].b,&e[i].c,&e[i].d);        if (e[i].c>e[i].d)swap(e[i].a,e[i].b),swap(e[i].c,e[i].d);        mx=max(mx,e[i].d); mn=min(mn,e[i].c);    }    int l=mn,r=mx,ans=-1;    while (l<=r){        int mid=(l+r)>>1;        if (check(mid)) r=mid-1;        else l=mid+1;    }    if (l<mx+1) printf("%d",l);    else printf("NIE");}


2 0
原创粉丝点击