POJ 3155 Hard Life 最大密度子圖

 
Hard Life
Time Limit: 8000MS   Memory Limit: 65536K
Total Submissions: 4345   Accepted: 1226
Case Time Limit: 2000MS   Special Judge

Description

John is a Chief Executive Officer at a privately owned medium size company. The owner of the company has decided to make his son Scott a manager in the company. John fears that the owner will ultimately give CEO position to Scott if he does well on his new manager position, so he decided to make Scott’s life as hard as possible by carefully selecting the team he is going to manage in the company.

John knows which pairs of his people work poorly in the same team. John introduced a hardness factor of a team — it is a number of pairs of people from this team who work poorly in the same team divided by the total number of people in the team. The larger is the hardness factor, the harder is this team to manage. John wants to find a group of people in the company that are hardest to manage and make it Scott’s team. Please, help him.

In the example on the picture the hardest team consists of people 1, 2, 4, and 5. Among 4 of them 5 pairs work poorly in the same team, thus hardness factor is equal to 54. If we add person number 3 to the team then hardness factor decreases to 65.

Input

The first line of the input file contains two integer numbers n and m (1 ≤ n ≤ 100, 0 ≤ m ≤ 1000). Here n is a total number of people in the company (people are numbered from 1 to n), and m is the number of pairs of people who work poorly in the same team. Next m lines describe those pairs with two integer numbers ai and bi (1 ≤ ai, bi n, aibi) on a line. The order of people in a pair is arbitrary and no pair is listed twice.

Output

Write to the output file an integer number k (1 ≤ kn) — the number of people in the hardest team, followed by k lines listing people from this team in ascending order. If there are multiple teams with the same hardness factor then write any one.

Sample Input

sample input #1
5 6
1 5
5 4
4 2
2 5
1 2
3 1

sample input #2
4 0

 

Sample Output

sample output #1
4
1
2
4
5

sample output #2
1
1

 

Hint

Note, that in the last example any team has hardness factor of zero, and any non-empty list of people is a valid answer.

Source

 
 

給定一個無向圖,要求它的一個子圖,使得子圖中邊數|E|與點數|V|的比值最大。

解法一:

假設答案爲,則要求解的問題是:選出一個合適的點集V和邊集E,令(|E| - k * |V|) 取得最大值。所謂合適是指滿足如下限制:若選擇某條邊,則必選擇其兩端點

建圖:以原圖的邊作爲左側頂點,權值爲1;原圖的點作爲右側頂點,權值爲-k(相當於 支出k)

若原圖中存在邊(u,v),則新圖中添加兩條邊([uv]-->u), ([uv]-->v),轉換爲最大權閉合子圖。

解法二:

把原圖中的無向邊轉換成兩條有向邊,容量爲1

設一源點,連接所有點,容量爲U(取m)。

設一匯點,所有點連接匯點,容量爲 U+2g-dv 

二分枚舉最大密度g,其中dvv的度。

判斷(U*n-MaxFlow)/2.>=0

最後跳出的L就是最大密度。

拿這個L再重新建圖,求最大流。

然後從s出發bfs或者dfs,走殘留容量大於0的邊,所有能到達的點就是答案。

具體分析過程見胡伯濤的論文《最小割模型在信息學競賽中的應用》

代碼:

	#include<cstdio>
	#include<cstring>
	#define N 1005
	#define inf 1<<30
	#define min(a,b) ((a)<(b)?(a):(b))
	int n,m,s,t,num,adj[N],dis[N],q[N],d[N];
	struct edge
	{
		int v,pre;
		double w;
	}e[10005];
	struct node
	{
		int u,v;
	}E[N];
	void insert(int u,int v,double w)
	{
		e[num]=(edge){v,adj[u],w};
		adj[u]=num++;
		e[num]=(edge){u,adj[v],0};
		adj[v]=num++;
	}
	int bfs()
	{
		int i,x,v,head=0,tail=0;
		memset(dis,0,sizeof(dis));
		dis[s]=1;
		q[++tail]=s;
		while(head!=tail)
		{
			x=q[head=(head+1)%N];
			for(i=adj[x];~i;i=e[i].pre)
				if(e[i].w>0&&!dis[v=e[i].v])
				{
					dis[v]=dis[x]+1;
					if(v==t)
						return 1;
					q[tail=(tail+1)%N]=v;
				}
		}
		return 0;
	}
	double dfs(int x,double limit)
	{
		if(x==t)
			return limit;
		int i,v;
		double tmp,cost=0;
		for(i=adj[x];~i&&cost<limit;i=e[i].pre)
			if(e[i].w>0&&dis[x]==dis[v=e[i].v]-1)
			{
				tmp=dfs(v,min(limit-cost,e[i].w));
				if(tmp)
				{
					e[i].w-=tmp;
					e[i^1].w+=tmp;
					cost+=tmp;
				}
				else
					dis[v]=-1;
			}
		return cost;
	}
	double Dinic()
	{
		double ans=0;
		while(bfs())
			ans+=dfs(s,inf);
		return ans;
	}
	int ok(double mid)
	{
		int i;
		memset(adj,-1,sizeof(adj));
		num=0;
		s=0;
		t=n+1;
		for(i=1;i<=m;i++)
		{
			insert(E[i].v,E[i].u,1);
			insert(E[i].u,E[i].v,1);
		}
		for(i=1;i<=n;i++)
		{
			insert(s,i,m);
			insert(i,t,m+2*mid-d[i]);
		}
		return (m*n-Dinic())/2.>=1e-6;
	}
	bool f[N];
	void dfs(int x)
	{
		f[x]=1;
		for(int v,i=adj[x];~i;i=e[i].pre)
			if(!f[v=e[i].v]&&e[i].w>0)
				dfs(v);
	}
	int main()
	{
		while(~scanf("%d%d",&n,&m))
		{
			int i,ans=0;
			memset(d,0,sizeof(d));
			for(i=1;i<=m;i++)
			{
				scanf("%d%d",&E[i].u,&E[i].v);
				d[E[i].u]++;
				d[E[i].v]++;
			}
			if(!m)
			{
				puts("1\n1\n");
				continue;
			}
			double l=0,r=m,mid;
			while(r-l>=1./n/n)
			{
				mid=(l+r)/2.;
				if(ok(mid))
					l=mid;
				else
					r=mid;
			}
			ok(l);
			memset(f,0,sizeof(f));
			dfs(s);
			for(i=1;i<=n;i++)
				ans+=f[i];
			printf("%d\n",ans);
			for(i=1;i<=n;i++)
				if(f[i])
					printf("%d\n",i);
		}
	}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章