题目链接
分析:网络流的题做多了看到这个就明白啥意思了,题意很明显,就是建一个二分图求一个最大匹配,并且要求每条匹配边的最大值最小,而对于最大值最小就二分答案准没错,而考虑一下是否具有单调性,对于答案ans,对于任意大于ans的值val跑出来的完美匹配,所以是具有单调性的。
然后问题就被转换成了,若最大边不超过mid,是否存在完美匹配。所以问题就成了一个判定问题,考虑怎么解决这个判定问题,每次二分一个值mid,不通过值大于mid的边增广,这样跑出来的是否是完美匹配。问题就解决了。
每次求最大流时不要忘了清空边的流量。
#include<bits/stdc++.h>
#define PII pair<int,int>
#define x first
#define y second
#define MAIN main
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=2e4+10;
struct edge
{
int u,v,cap,flow,num;
edge(int u=0,int v=0,int cap=0,int flow=0,int num=0):u(u),v(v),cap(cap),flow(flow),num(num){}
};
vector<edge>E;
vector<int>g[N];
void add(int u,int v,int cap,int num)
{
E.push_back(edge(u,v,cap,0,num));
E.push_back(edge(v,u,0,0,num));
int m=E.size();
g[u].push_back(m-2);
g[v].push_back(m-1);
}
int n,m;
int vis[N],d[N],cur[N];
int bfs(int s,int t,int mid)
{
memset(vis,0,sizeof(vis));
queue<int>q;
q.push(s);
vis[s]=1;d[s]=0;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<(int)g[u].size();i++){
edge &e=E[g[u][i]];
if(e.num>mid) continue;
int v=e.v;
if(!vis[v]&&e.cap>e.flow){
vis[v]=1;
d[v]=d[u]+1;
q.push(v);
}
}
}
return vis[t];
}
int dfs(int s,int t,int a,int mid)
{
if(s==t||a==0) return a;
int flow=0,f;
for(int &i=cur[s];i<(int)g[s].size();i++){
edge &e=E[g[s][i]];
if(e.num>mid) continue;
int v=e.v;
if(d[v]==d[s]+1&&(f=dfs(v,t,min(a,e.cap-e.flow),mid))>0){
flow+=f;
e.flow+=f;
E[g[s][i]^1].flow-=f;
a-=f;
if(a==0) break;
}
}
return flow;
}
int max_flow(int s,int t,int mid)
{
int flow=0;
while(bfs(s,t,mid))
{
memset(cur,0,sizeof(cur));
flow+=dfs(s,t,INF,mid);
}
return flow;
}
int s,t;
bool judge(int mid)
{
for(int i=0;i<(int)E.size();i++) E[i].flow=0;
int flow=max_flow(s,t,mid);
if(flow==n) return true;
return false;
}
int MAIN()
{
scanf("%d%d",&n,&m);
s=0,t=2*n+1;
for(int i=1;i<=m;i++){
int u,v,d;
scanf("%d%d%d",&u,&v,&d);
add(u,v+n,1,d);
}
for(int i=1;i<=n;i++){
add(s,i,1,0);
add(i+n,t,1,0);
}
int l=0,r=1e9,mid,ans=-1;
while(l<=r)
{
mid=(l+r)>>1;
if(judge(mid)) r=mid-1,ans=mid;
else l=mid+1;
}
printf("%d\n",ans);
return 0;
}