YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛。现在YYD想骑单车从小岛1出发,骑过每一座桥,到达每一个小岛,然后回到小岛1。霸中同学为了让YYD减肥成功,召唤了大风,由于是海上,风变得十分大,经过每一座桥都有不可避免的风阻碍YYD,YYD十分ddt,于是用泡芙贿赂了你,希望你能帮他找出一条承受的最大风力最小的路线。
输入:第一行为两个用空格隔开的整数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。
注意:通过桥为欧拉回路
二分答案之后只有小于等于mid的桥可以保留,有的是单向,有的是无向。
验证需要求无向图欧拉回路:
1:先检验每个点入度是否为偶数,这是最先的。
2:将每条无向边定向(随便定)。
3:每个点需要入度等于出度,但是随机定向不能满足。
出度大于入度的点,需要 出边改向数 - 入边改向数 = (outdrg - indrg) / 2
出度小于入度的点,需要 入边改向数 - 出边改向数 = (-outdrg + indrg) / 2
如果我们认为:1流量从定了向的无向边(也就是有向边)流往点A表示这条A的入边改向为出边,1流量从定了向的无向边(也就是有向边)流出点A表示这条A的出边改向为入边,那么根据流量守恒,出度大于入度的点需要从源点流入 (outdrg - indrg) / 2,而出度小于入度的点需要流向汇点(-outdrg + indrg) / 2,满流即有方案。
AC Code:
#include<bits/stdc++.h>
#define maxn 1005
#define maxm 10005
#define inf 0x3f3f3f3f
#define Clear(a,b) memset(a,b,sizeof a)
#define Copy(a,b) memcpy(a,b,sizeof a)
using namespace std;
int n,m,a[maxm],b[maxm],c[maxm],d[maxm];
int info[maxn],Prev[maxm],to[maxm],cap[maxm],cnt_e=1;
void Node(int u,int v,int c){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cap[cnt_e]=c; }
void Line(int u,int v,int c){ Node(u,v,c),Node(v,u,0); }
int S,T,h[maxn],g[maxn],buf[maxn],ot[maxn],vis[maxn],sb[maxn<<1];
void dfs(int u){ vis[u]=1; for(int i=info[u];i;i=Prev[i]) if(!vis[to[i]]) dfs(to[i]); }
int aug(int u,int mx){
if(u == T) return mx;
int st = mx , inc;
for(int &i=info[u],v;i;i=Prev[i])
if(cap[i] && h[v=to[i]]+1 == h[u] && (inc = aug(v,min(cap[i],st)))){
cap[i] -= inc , cap[i^1] += inc;
if(!(st-=inc) || h[0]) return mx-st;
}
if(!--g[h[u]]) h[0]=1;
++g[++h[u]];info[u]=buf[u];
return mx-st;
}
int main(){
freopen("bridges.in","r",stdin);
freopen("bridges.out","w",stdout);
scanf("%d%d",&n,&m);S=n+1,T=n+2;
int mx = 0;
for(int i=1;i<=m;i++) scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]),mx=max(mx,min(c[i],d[i])),Line(a[i],b[i],0),ot[a[i]]++,ot[b[i]]++,sb[++sb[0]]=c[i],sb[++sb[0]]=d[i];
dfs(1);
for(int i=1;i<=n;i++) if(!vis[i] || (ot[i]&1)){
puts("NIE");
return 0;
}
sort(sb+1,sb+1+sb[0]),sb[0]=unique(sb+1,sb+1+sb[0])-sb-1;
int L=lower_bound(sb+1,sb+1+sb[0],mx)-sb,R=sb[0],mid;
for(;L<R;){
mid=(L+R) >> 1;
Clear(info,0),Clear(ot,0),cnt_e=1;
for(int i=1;i<=m;i++) if(c[i]<=sb[mid]){
ot[a[i]]++,ot[b[i]]--;
if(d[i]<=sb[mid]) Line(a[i],b[i],1);
}else ot[a[i]]--,ot[b[i]]++;
int stm = 0;
for(int i=1;i<=n;i++) if(ot[i]>0) Line(S,i,ot[i]/2),stm+=ot[i]/2;
else if(ot[i]<0) Line(i,T,-ot[i]/2);
for(Clear(h,0),Clear(g,0),Copy(buf,info);!h[0];) stm-=aug(S,inf);
if(stm) L=mid+1;
else R=mid;
}
printf("%d\n",sb[L]);
}