POJ 3155 Hard Life 最大密度子图

来源:互联网 发布:哈尔滨黑夜骑士网络 编辑:程序博客网 时间:2024/05/17 06:32
 
Hard Life
Time Limit: 8000MS Memory Limit: 65536KTotal Submissions: 4345 Accepted: 1226Case 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 aiand bi (1 ≤ aibi ≤ nai ≠ bi) 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 ≤ k ≤ n) — 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

Northeastern Europe 2006
 
 

给定一个无向图,要求它的一个子图,使得子图中边数|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的边,所有能到达的点就是答案。

具体分析过程见胡伯涛的论文《最小割模型在信息学竞赛中的应用》

代码:

[cpp] view plain copy
  1. #include<cstdio>  
  2. #include<cstring>  
  3. #define N 1005  
  4. #define inf 1<<30  
  5. #define min(a,b) ((a)<(b)?(a):(b))  
  6. int n,m,s,t,num,adj[N],dis[N],q[N],d[N];  
  7. struct edge  
  8. {  
  9.     int v,pre;  
  10.     double w;  
  11. }e[10005];  
  12. struct node  
  13. {  
  14.     int u,v;  
  15. }E[N];  
  16. void insert(int u,int v,double w)  
  17. {  
  18.     e[num]=(edge){v,adj[u],w};  
  19.     adj[u]=num++;  
  20.     e[num]=(edge){u,adj[v],0};  
  21.     adj[v]=num++;  
  22. }  
  23. int bfs()  
  24. {  
  25.     int i,x,v,head=0,tail=0;  
  26.     memset(dis,0,sizeof(dis));  
  27.     dis[s]=1;  
  28.     q[++tail]=s;  
  29.     while(head!=tail)  
  30.     {  
  31.         x=q[head=(head+1)%N];  
  32.         for(i=adj[x];~i;i=e[i].pre)  
  33.             if(e[i].w>0&&!dis[v=e[i].v])  
  34.             {  
  35.                 dis[v]=dis[x]+1;  
  36.                 if(v==t)  
  37.                     return 1;  
  38.                 q[tail=(tail+1)%N]=v;  
  39.             }  
  40.     }  
  41.     return 0;  
  42. }  
  43. double dfs(int x,double limit)  
  44. {  
  45.     if(x==t)  
  46.         return limit;  
  47.     int i,v;  
  48.     double tmp,cost=0;  
  49.     for(i=adj[x];~i&&cost<limit;i=e[i].pre)  
  50.         if(e[i].w>0&&dis[x]==dis[v=e[i].v]-1)  
  51.         {  
  52.             tmp=dfs(v,min(limit-cost,e[i].w));  
  53.             if(tmp)  
  54.             {  
  55.                 e[i].w-=tmp;  
  56.                 e[i^1].w+=tmp;  
  57.                 cost+=tmp;  
  58.             }  
  59.             else  
  60.                 dis[v]=-1;  
  61.         }  
  62.     return cost;  
  63. }  
  64. double Dinic()  
  65. {  
  66.     double ans=0;  
  67.     while(bfs())  
  68.         ans+=dfs(s,inf);  
  69.     return ans;  
  70. }  
  71. int ok(double mid)  
  72. {  
  73.     int i;  
  74.     memset(adj,-1,sizeof(adj));  
  75.     num=0;  
  76.     s=0;  
  77.     t=n+1;  
  78.     for(i=1;i<=m;i++)  
  79.     {  
  80.         insert(E[i].v,E[i].u,1);  
  81.         insert(E[i].u,E[i].v,1);  
  82.     }  
  83.     for(i=1;i<=n;i++)  
  84.     {  
  85.         insert(s,i,m);  
  86.         insert(i,t,m+2*mid-d[i]);  
  87.     }  
  88.     return (m*n-Dinic())/2.>=1e-6;  
  89. }  
  90. bool f[N];  
  91. void dfs(int x)  
  92. {  
  93.     f[x]=1;  
  94.     for(int v,i=adj[x];~i;i=e[i].pre)  
  95.         if(!f[v=e[i].v]&&e[i].w>0)  
  96.             dfs(v);  
  97. }  
  98. int main()  
  99. {  
  100.     while(~scanf("%d%d",&n,&m))  
  101.     {  
  102.         int i,ans=0;  
  103.         memset(d,0,sizeof(d));  
  104.         for(i=1;i<=m;i++)  
  105.         {  
  106.             scanf("%d%d",&E[i].u,&E[i].v);  
  107.             d[E[i].u]++;  
  108.             d[E[i].v]++;  
  109.         }  
  110.         if(!m)  
  111.         {  
  112.             puts("1\n1\n");  
  113.             continue;  
  114.         }  
  115.         double l=0,r=m,mid;  
  116.         while(r-l>=1./n/n)  
  117.         {  
  118.             mid=(l+r)/2.;  
  119.             if(ok(mid))  
  120.                 l=mid;  
  121.             else  
  122.                 r=mid;  
  123.         }  
  124.         ok(l);  
  125.         memset(f,0,sizeof(f));  
  126.         dfs(s);  
  127.         for(i=1;i<=n;i++)  
  128.             ans+=f[i];  
  129.         printf("%d\n",ans);  
  130.         for(i=1;i<=n;i++)  
  131.             if(f[i])  
  132.                 printf("%d\n",i);  
  133.     }  
  134. }