【BZOJ】【P1532】【POI2005】【Kos-Dicing】【二分+最大流】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012732945/article/details/39667859

传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1532

最大值最小显然要二分

然后就是如何判定了

s->每场比赛 cap=1

每场比赛->对战双方 cap=1

每个选手->t cap=二分的答案

可行的话应该是满流的

然后你发现这是一个二分图

dinic跑二分图的优越性就体现了出来

总复杂度就变成了O(sqrt(n+m)*(n+m)*logm)

不知道sap能不能过

SAP过不了啦啦啦


Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e4+10;
struct edge{
	int u,v,cap,flow;
};
vector<edge>edges;
vector<int>G[maxn];
void add(int u,int v,int cap){
	edges.push_back((edge){u,v,cap,0});
	G[u].push_back(edges.size()-1);
	edges.push_back((edge){v,u,0,0});
	G[v].push_back(edges.size()-1);
}
int n,m,s,t;
int vis[maxn],d[maxn],cur[maxn];
bool bfs(){
	memset(vis,0,sizeof vis);vis[s]=1;
	queue<int>q;q.push(s);d[s]=0;
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=0;i<G[u].size();++i){
			edge e=edges[G[u][i]];
			if(!vis[e.v]&&e.cap>e.flow){
				vis[e.v]=1;
				d[e.v]=d[u]+1;
				q.push(e.v);
			}
		}
	}return vis[t];
}
int dfs(int u,int a){
	if(u==t||!a)return a;
	int flow=0,f;
	for(int &i=cur[u];i<G[u].size();i++){
		edge e=edges[G[u][i]];
		if(d[e.v]==d[u]+1&&(f=dfs(e.v,min(a,e.cap-e.flow)))>0){
			flow+=f;
			a-=f;
			edges[G[u][i]].flow+=f;
			edges[G[u][i]^1].flow-=f;
			if(!a)break;
		}
	}return flow;
}
int Dinic(){
	int flow=0,x;
	while(bfs()){
		memset(cur,0,sizeof cur);
		while(x=dfs(s,INT_MAX)){
			flow+=x;
			memset(cur,0,sizeof cur);
		}
	}return flow;
}
int main(){
	scanf("%d%d",&n,&m);
	s=0;t=n+m+1;
	for(int i=1;i<=m;i++){
		int u,v;scanf("%d%d",&u,&v);
		add(s,i,1);
		add(i,u+m,1);
		add(i,v+m,1);
	}
	int lf=edges.size();
	for(int i=1;i<=n;i++)add(i+m,t,0);
	int l=1,r=m;
	while(l<r){
		int mid=(l+r)>>1;
		for(int i=0;i<edges.size();i++)edges[i].flow=0;
		for(int i=lf;i<edges.size();i++)edges[i].cap=mid;
		if(Dinic()<m)
			l=mid+1;
		else
			r=mid;
	}cout<<l<<endl;
	return 0;
}


展开阅读全文

没有更多推荐了,返回首页