好题\(Q\omega Q\)
我们考虑这个东西要求最大值最小,显然一眼二分答案对吧.
问题在于如何\(check\),我们二分答案之后把问题转换成了混合图如何求欧拉回路.
考虑欧拉回路的性质,每一个点的入度要\(=\)出度.
但是存在无向边,我们先随便让它选择一个方向,然后连一条反向边,容量为1.
这样子我们考虑选这样子一条边意味着让一个点的入度与出度的差 减少/增加 2.
然后直接跑最大流判断是否满流即可.
/* mail: mleautomaton@foxmail.com author: MLEAutoMaton This Code is made by MLEAutoMaton */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<algorithm> #include<queue> #include<set> #include<map> #include<iostream> using namespace std; #define ll long long #define re register #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout) inline int gi(){ int f=1,sum=0;char ch=getchar(); while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return f*sum; } const int N=2010,Inf=1e9+10; int n,m,front[N],cnt,dep[N],cur[N],s,t,d[N];queue<int>Q; struct node{int to,nxt,w;}e[N*20]; void Add(int u,int v,int w){ e[cnt]=(node){v,front[u],w};front[u]=cnt++; e[cnt]=(node){u,front[v],0};front[v]=cnt++; } struct edge{int u,v,c,d;}edg[N]; bool bfs(){ Q.push(s);memset(dep,0,sizeof(dep));dep[s]=1; while(!Q.empty()){ int u=Q.front();Q.pop(); for(int i=front[u];~i;i=e[i].nxt){ int v=e[i].to; if(!dep[v] && e[i].w){ dep[v]=dep[u]+1;Q.push(v); } } } return dep[t]; } int dfs(int u,int flow){ if(u==t || !flow)return flow; for(int &i=cur[u];~i;i=e[i].nxt){ int v=e[i].to; if(dep[v]==dep[u]+1 && e[i].w){ int di=dfs(v,min(e[i].w,flow)); if(di){ e[i].w-=di;e[i^1].w+=di;return di; } else dep[v]=0; } } return 0; } int Dinic(){ int flow=0; while(bfs()){ for(int i=s;i<=t;i++)cur[i]=front[i]; while(int d=dfs(s,Inf))flow+=d; } return flow; } int build(int mid){ memset(front,-1,sizeof(front));cnt=0; memset(d,0,sizeof(d));int tot=0;s=0;t=n+1; for(int i=1;i<=m;i++){ int C=edg[i].c,D=edg[i].d; if(C<=mid){d[edg[i].u]--;d[edg[i].v]++;} if(D<=mid)Add(edg[i].v,edg[i].u,1); } for(int i=1;i<=n;i++) if(d[i]&1)return 0; for(int i=1;i<=n;i++) if(d[i]>0)Add(s,i,d[i]/2),tot+=d[i]/2; else Add(i,t,-d[i]/2); return tot+1; } bool check(int mid){ int tot=build(mid); if(!tot)return false; tot--; return Dinic()==tot; } int main(){ #ifndef ONLINE_JUDGE freopen("in.in","r",stdin); #endif n=gi();m=gi();int l=Inf,r=-Inf; for(int i=1;i<=m;i++){ edg[i].u=gi(),edg[i].v=gi(),edg[i].c=gi(),edg[i].d=gi(); if(edg[i].c>edg[i].d) swap(edg[i].u,edg[i].v),swap(edg[i].c,edg[i].d); l=min(l,edg[i].c);r=max(r,edg[i].d); } int ret=0; while(l<=r){ int mid=(l+r)>>1; if(check(mid)){r=mid-1;ret=mid;} else l=mid+1; } if(ret)printf("%d\n",ret); else puts("NIE"); return 0; }
来源:https://www.cnblogs.com/mleautomaton/p/11253170.html