1. 程式人生 > >bzoj 2095 [Poi2010]Bridges 判斷歐拉維護,最大流+二分

bzoj 2095 [Poi2010]Bridges 判斷歐拉維護,最大流+二分

OS next math ans 由於 src int sed php

[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 判斷歐拉維護,最大流+二分