ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【UVA1389】Hard Life(分数规划+网络流)

2021-05-10 22:04:03  阅读:248  来源: 互联网

标签:Life UVA1389 ee Hard 子图 int lnk Dinic define


点此看题面

  • 给定一张\(n\)个点\(m\)条边的无向图,求最大密度子图(即边数除以点数最大的导出子图)。
  • \(n\le100,m\le1000\)

分数规划

这种问题一看就是分数规划。

我们直接二分答案\(x\),则\(\frac EP\ge x\)就可以写成\(E-x\times P\ge 0\)。

即选择每条边的价值是\(1\),每个点的价值是\(-x\)。

最大权闭合子图

考虑只有选了两个端点,才能选择这条边,是一个经典的最大权闭合子图模型。

注意有可能不选任何点会取得最优价值,因此我们最大流之后需要加上判断选择的点数不为\(0\)。

至于如何判断一个点是否被选择,根据最大权闭合子图模型的建图方式,断开与超级汇相连的边表示选择,那么此时就与超级源连通。即从超级源出发存在一条到该点的增广路径,也就是最后一次\(BFS\)时的\(dep\not=-1\)。

\(O(Dinic)\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100
#define M 1000
#define INF 1e9
#define DB double
using namespace std;
int n,m;struct line {int x,y;}p[M+5];
namespace Dinic
{
	#define PS (N+M+2)
	#define ES (N+3*M)
	#define s (n+m+1)
	#define t (n+m+2)
	#define E(x) ((((x)-1)^1)+1)
	#define add(x,y,f) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].F=f)
	int ee,lnk[PS+5],cur[PS+5];struct edge {int to,nxt;DB F;}e[2*ES+5];
	I void Cl() {ee=0;for(RI i=1;i<=t;++i) lnk[i]=0;}
	I void Add(CI x,CI y,Con DB& f) {add(x,y,f),add(y,x,0);}
	int q[PS+5],D[PS+5];I bool BFS()
	{
		RI i,k,H=1,T=1;for(i=1;i<=t;++i) D[i]=-1;D[q[1]=s]=0;
		W(H<=T&&!~D[t]) for(i=lnk[k=q[H++]];i;i=e[i].nxt)
			e[i].F&&!~D[e[i].to]&&(D[q[++T]=e[i].to]=D[k]+1);return ~D[t];
	}
	I DB DFS(CI x=s,DB f=INF)
	{
		if(x==t||!f) return f;RI i;DB o,g=0;for(i=cur[x];i;i=e[i].nxt)
		{
			if(D[e[i].to]^(D[x]+1)||!(o=DFS(e[i].to,min(f,e[i].F)))) continue;
			if(g+=o,e[i].F-=o,e[E(i)].F+=o,!(f-=o)) break;
		}return cur[x]=i,g;
	}
	I DB MaxFlow(Con DB& x)//最大权闭合子图模型
	{
		RI i;for(Cl(),i=1;i<=n;++i) Add(i,t,x);//点向超级汇
		for(i=1;i<=m;++i) Add(s,n+i,1),Add(n+i,p[i].x,INF),Add(n+i,p[i].y,INF);//超级源向边,边向点
		DB f=0;W(BFS()) memcpy(cur,lnk,sizeof(cur)),f+=DFS();return f;//最大流
	}
	I bool Check(CI x) {return ~D[x];}//判断是否选择(是否与超级源连通)
}
int main()
{
	RI i,c;DB l,r,mid,res;W(scanf("%d%d",&n,&m)==2)
	{
		for(i=1;i<=m;++i) scanf("%d%d",&p[i].x,&p[i].y);
		if(!m) {puts("1\n1\n");continue;}//特判没有边的情况
		l=0,r=m;W(r-l>1e-6) {res=m-Dinic::MaxFlow(mid=(l+r)/2);//分数规划
			for(i=1;i<=n;++i) if(Dinic::Check(i)) break;i<=n&&res>0?l=mid:r=mid;}//必须有点被选择
		for(Dinic::MaxFlow(l),c=0,i=1;i<=n;++i) Dinic::Check(i)&&++c;printf("%d\n",c);
		for(i=1;i<=n;++i) Dinic::Check(i)&&printf("%d\n",i);putchar('\n');
	}return 0;
}

标签:Life,UVA1389,ee,Hard,子图,int,lnk,Dinic,define
来源: https://www.cnblogs.com/chenxiaoran666/p/UVA1389.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有