BZOJ 2095 Bridges

题目传送门

分析:

首先就是二分

然后。。。

混合图欧拉回路是sm。。。

看了题解Orz

首先要回到原来的点的话,那么每个点入度和出度要相等。。。

这。。和网络流进入点之后就出去不是一样的吗。。

又由于有的边可以反向

反向后又会改变两个点+-2的流量

于是考虑上下界网络流

每条单向边容量设为1

每条双向边随便定向,连(-1,1)的边

wsm会出现负数?因为-1可以代表反向流

但是貌似并不影响上下界网络流诶。。。

哦摩西罗伊2333

直接跑就好了

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>

#define maxn 3005
#define maxm 500005
#define INF 0x3f3f3f3f

using namespace std;

inline int getint()
{
    int num=0,flag=1;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    return num*flag;
}

int n,m,S,T;
int fir[maxn],nxt[maxm],to[maxm],cap[maxm],cnt;
int h[maxn],tp[maxn];
struct node{
    int a,b,c,d;
}E[maxm];
int f[maxn];

inline void newnode(int u,int v,int w)
{to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,cap[cnt]=w;}
inline void insert(int u,int v,int w)
{newnode(u,v,w),newnode(v,u,0);}

inline bool bfs()
{
    memset(h,-1,sizeof h);
    queue<int>Q;h[S]=0,Q.push(S);
    while(!Q.empty())
    {
        int u=Q.front();Q.pop();
        for(int i=fir[u];i;i=nxt[i])
            if(cap[i]&&!~h[to[i]])h[to[i]]=h[u]+1,Q.push(to[i]);
    }
    return ~h[T];
}

inline int dfs(int u,int flow)
{
    if(u==T)return flow;
    int used=0;
    for(int i=tp[u];i;i=nxt[i])
    {
        tp[u]=i;
        if(cap[i]&&h[to[i]]==h[u]+1)
        {
            int w=flow-used;
            w=dfs(to[i],min(cap[i],w));
            cap[i]-=w,cap[i^1]+=w,used+=w;
            if(used==flow)return flow;
        }
    }
    if(!used)h[u]=-1;
    return used;
}

inline int dinic()
{
    int num=0;
    while(bfs())memcpy(tp,fir,sizeof fir),num+=dfs(S,INF);
    return num;
}

inline bool check(int num)
{
    memset(fir,0,sizeof fir);cnt=1;
    memset(f,0,sizeof f);
    for(int i=1;i<=m;i++)
    {
        if(E[i].c<=num&&E[i].d<=num)f[E[i].a]--,f[E[i].b]++,insert(E[i].b,E[i].a,2);
        else if(E[i].c<=num)f[E[i].a]--,f[E[i].b]++;
        else if(E[i].d<=num)f[E[i].b]--,f[E[i].a]++;
        else return 0;
    }
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        if(f[i]&1)return 0;
        if(f[i]>0)insert(S,i,f[i]),sum+=f[i];
        else insert(i,T,-f[i]);
    }
    return sum==dinic();
}

int main()
{
    n=getint(),m=getint();S=n+1,T=S+1;
    for(int i=1;i<=m;i++)E[i].a=getint(),E[i].b=getint(),E[i].c=getint(),E[i].d=getint();
    int l=0,r=INF;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    }
    if(l==INF)printf("NIE\n");
    else printf("%d\n",l);
}
View Code

 

 

posted @ 2019-12-10 16:08  Izayoi_Doyo  阅读(247)  评论(0编辑  收藏  举报