UVA1389 Hard Life (01分数规划+最大流)

UVA1389 Hard Life (01分数规划+最大流)

Luogu

题目描述略

题解时间

$ (\frac{\Sigma EdgeCount}{\Sigma PointCount})_{max} $

是什么已经不用说了⑧

经典的01分数规划

上来先二分答案$ ans $

之后考虑判断

根据选边与选点的关系

考虑建出这样一个图:

建立源点 $ S $ 与汇点 $ P $

对于原图中的每条边看做一个点,从 $ S $ 向这个点建流量为 $ 1 $ 的边

对于原图中的每个点向 $ T $ 建流量为 $ ans $ 的边

对于原图中的每条边所代表的点,向这条边连接的两个点建流量为 $ 1 $ 的边

跑最大流, $ maxflow \leq m $ 即可

原理?

我们回顾一下柿子

$ \frac{\Sigma EdgeCount}{\Sigma PointCount} \leq ans $

转换一下就是

$ \Sigma EdgeCount-\Sigma PointCount*ans \leq 0 $

好像已经很明显了⑧

那就先这样吧(溜走)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
namespace LarjaIX
{
const int N=2011;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const double dinf=1e8;
struct sumireko{int to,ne;double w;}e[N<<2];
int he[N],ecnt=1;
void addline(int f,int t,double w)
{
	e[++ecnt].to=t,e[ecnt].w=w;
	e[ecnt].ne=he[f],he[f]=ecnt;
	e[++ecnt].to=f,e[ecnt].w=0;
	e[ecnt].ne=he[t],he[t]=ecnt;
}
int head[N],dep[N];
queue<int>q;
bool ins[N];
bool bfs(int sp,int ep)
{
	memcpy(head,he,sizeof(head));
	memset(dep,0x3f,sizeof(dep));
	dep[sp]=1,q.push(sp);
	while(!q.empty())
	{
		int x=q.front();q.pop();
		for(int ei=he[x],t=e[ei].to;ei;ei=e[ei].ne,t=e[ei].to)
		if(dep[t]==inf&&e[ei].w>eps) dep[t]=dep[x]+1,q.push(t);
	}
	return dep[ep]!=inf;
}
double dfs(int x,double lim,int ep)
{
	if(x==ep||lim<eps) return lim;
	double ret=0,tmp=0;
	for(int ei=head[x],t=e[ei].to;ei;ei=e[ei].ne,t=e[ei].to)
	{
		head[x]=ei;
		if(dep[t]==dep[x]+1)if((tmp=dfs(t,min(e[ei].w,lim),ep))>eps)
		{
			lim-=tmp,ret+=tmp;
			e[ei].w-=tmp,e[ei^1].w+=tmp;
			if(lim<eps) break;
		}
	}
	return ret;
}
double dinic(int sp,int ep)
{
	double ret=0;
	while(bfs(sp,ep)) ret+=dfs(sp,dinf,ep);
	return ret;
}
int n,m;
int lx[N],ly[N];
int maid()
{
	while(~scanf("%d%d",&n,&m))
	{
		if(!m){puts("1");puts("1");continue;}
		for(int i=1;i<=m;i++) scanf("%d%d",&lx[i],&ly[i]);
		double ansl=0,ansr=m,ansm=0,eeps=1.0/n/n;
		while(ansr-ansl>eeps)
		{
			ansm=(ansl+ansr)/2;
			for(int i=1;i<=m;i++) addline(n+i,lx[i],1.0),addline(n+i,ly[i],1.0);
			for(int i=1;i<=m;i++) addline(n+m+1,n+i,1.0);
			for(int i=1;i<=n;i++) addline(i,n+m+2,ansm);
			double tmp=dinic(n+m+1,n+m+2);
			if((double)m-tmp>eps) ansl=ansm;
			else ansr=ansm;
			ecnt=1,memset(he,0,sizeof(he));
		}
		ansm=ansl;
		for(int i=1;i<=m;i++) addline(n+i,lx[i],dinf),addline(n+i,ly[i],dinf);
		for(int i=1;i<=m;i++) addline(n+m+1,n+i,1.0);
		for(int i=1;i<=n;i++) addline(i,n+m+2,ansm);
		dinic(n+m+1,n+m+2);
		bfs(n+m+1,n+m+2);
		int ans=0;
		for(int i=1;i<=n;i++) if(dep[i]!=inf) ans++;
		printf("%d\n",ans);
		for(int i=1;i<=n;i++) if(dep[i]!=inf) printf("%d\n",i);
		ecnt=1,memset(he,0,sizeof(he));
	}
	return 0;
}
}
int main(){return LarjaIX::maid();}
posted @ 2019-11-26 21:31  RikukiIX  阅读(216)  评论(0编辑  收藏  举报