bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分

Posted Kaiser

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分相关的知识,希望对你有一定的参考价值。

 [Poi2010]Bridges

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 1448  Solved: 510
[Submit][Status][Discuss]

Description

YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛。现在YYD想骑单车从小岛1出发,骑过每一座桥,到达每一个小岛,然后回到小岛1。霸中同学为了让YYD减肥成功,召唤了大风,由于是海上,风变得十分大,经过每一座桥都有不可避免的风阻碍YYD,YYD十分ddt,于是用泡芙贿赂了你,希望你能帮他找出一条承受的最大风力最小的路线。

Input

输入:第一行为两个用空格隔开的整数n(2<=n<=1000),m(1<=m<=2000),接下来读入m行由空格隔开的4个整数a,b(1<=a,b<=n,a<>b),c,d(1<=c,d<=1000),表示第i+1行第i座桥连接小岛a和b,从a到b承受的风力为c,从b到a承受的风力为d。

Output

输出:如果无法完成减肥计划,则输出NIE,否则第一行输出承受风力的最大值(要使它最小)

Sample Input

4 4
1 2 2 4
2 3 3 4
3 4 4 4
4 1 5 4
技术分享图片

Sample Output

4

HINT

 

注意:通过桥为欧拉回路

 

 

 

Source

 

 题解:二分风力值,然后最大流判断欧拉回路是否存在。
 
  1 #include<queue>
  2 #include<cmath>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<algorithm>
  7 
  8 #define inf 1000000000
  9 #define pa pair<int,int>
 10 #define ll long long 
 11 #define mod 1000000007
 12 using namespace std;
 13 ll read()
 14 {
 15     ll x=0,f=1;char ch=getchar();
 16     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
 17     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
 18     return x*f;
 19 }
 20 
 21 int tot,n,m,cnt,T;
 22 int mx,mn=inf;
 23 int u[2005],v[2005],c[2005],d[2005],de[2005];
 24 int last[2005],q[2005],h[2005];
 25 struct edge{
 26     int to,next,v;
 27 }e[1000005];
 28 
 29 void insert(int u,int v,int w)
 30 {
 31     e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w;
 32     e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=0;
 33 }
 34 bool bfs()
 35 {
 36     int head=0,tail=1;
 37     for(int i=0;i<=T;i++)h[i]=-1;
 38     q[0]=0;h[0]=0;
 39     while(head!=tail)
 40     {
 41         int now=q[head];head++;
 42         for(int i=last[now];i;i=e[i].next)
 43             if(e[i].v&&h[e[i].to]==-1)
 44             {
 45                 h[e[i].to]=h[now]+1;
 46                 q[tail++]=e[i].to;
 47             }
 48     }
 49     return h[T]!=-1;
 50 }
 51 int dfs(int x,int f)
 52 {
 53     if(x==T)return f;
 54     int w,used=0;
 55     for(int i=last[x];i;i=e[i].next)
 56         if(h[e[i].to]==h[x]+1)
 57         {
 58             w=dfs(e[i].to,min(e[i].v,f-used));
 59             e[i].v-=w,e[i^1].v+=w;
 60             used+=w;if(used==f)return f;
 61         }
 62     if(!used)h[x]=-1;
 63     return used;
 64 }
 65 void build(int mid)
 66 {
 67     memset(last,0,sizeof(last));cnt=1;
 68     memset(de,0,sizeof(de));
 69     tot=0;
 70     for(int i=1;i<=m;i++)
 71     {
 72         if(c[i]<=mid)de[u[i]]--,de[v[i]]++;
 73         if(d[i]<=mid)insert(v[i],u[i],1);
 74     }
 75     for(int i=1;i<=n;i++)
 76         if(de[i]>0)tot+=de[i]/2,insert(0,i,de[i]/2);
 77         else insert(i,T,-de[i]/2);
 78 }
 79 int dinic()
 80 {
 81     for(int i=1;i<=n;i++)
 82         if(de[i]&1)return -1;
 83     int ans=0;
 84     while(bfs())ans+=dfs(0,inf);
 85     return ans;
 86 }
 87 int main()
 88 {
 89     n=read();m=read();T=n+1;
 90     for(int i=1;i<=m;i++)
 91     {
 92         u[i]=read(),v[i]=read(),c[i]=read(),d[i]=read();
 93         if(c[i]>d[i])swap(c[i],d[i]),swap(u[i],v[i]);
 94         mn=min(mn,c[i]);
 95         mx=max(mx,d[i]);
 96     }
 97     int l=mn,r=mx;
 98     while(l<=r)
 99     {
100         int mid=(l+r)>>1;
101         build(mid);
102         if(dinic()==tot) r=mid-1;
103         else l=mid+1;
104     }
105     if(l==mx+1)puts("NIE");
106     else printf("%d\n",l);
107 }

 

以上是关于bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj2095 [Poi2010]Bridges

BZOJ2095[Poi2010]Bridges 动态加边网络流

bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分

*BZOJ2095: [Poi2010]Bridges

bzoj 2095 Poi2010 Bridges 混合图欧拉回路

bzoj 2095: [Poi2010]Bridges(二分法+混合图的欧拉回路)