POJ 3155 Hard Life(最大密度子图)
来源:互联网 发布:au mac卡顿 编辑:程序博客网 时间:2024/05/17 22:33
Hard Life
Time Limit: 8000MS Memory Limit: 65536K
Total Submissions: 9111 Accepted: 2648
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 5⁄4. If we add person number 3 to the team then hardness factor decreases to 6⁄5.
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, ai ≠ 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
题目大意:
有一张无向无权图,让你找出一个子图,使得子图中的边数/顶点数最大。
解题思路:
最大密度子图的最简单情况,详细解法胡伯涛的《最小割模型在信息学中的应用》。这里只做简要说明。
首先,最大密度子图是一个01分数规划问题,我们所使用的求解方法就是求解01分数规划问题的方法。
记
建图方式如下:首先定义一个足够大的常量
这里有一个细节,由于我们建成的图的最大流一定不会超过
这个写法还可以向边带权的无向图,以及点边都带权的无向图扩展。
对于边带非负权的无向图:答案之间不再有最小差值,我们需要规定二分的精度。常量U需要该为所有边权值之和。重新定义
对于边带非负权点带可正可负的权值的无向图:同样需要规定二分精度。常量U该为点权绝对值和的两倍加上边权和。同样重新定义
AC代码:
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <ctime>#include <vector>#include <queue>#include <stack>#include <deque>#include <string>#include <map>#include <set>#include <list>using namespace std;#define INF 0x3f3f3f3f#define LL long long#define fi first#define se second#define mem(a,b) memset((a),(b),sizeof(a))const double eps=1e-8;const int MAXV=100+3;const int MAXE=1000+3;struct Edge{ int to, rev; double cap; Edge(int t, double c, int r):to(t), cap(c), rev(r){}};pair<int, int> edge[MAXE];int N, V, E, U, cnt;int deg[MAXV];//原图中点的度数vector<Edge> G[MAXV];int level[MAXV];int iter[MAXV];bool vis[MAXV];void add_edge1(int from, int to, double cap)//建立有向边{ G[from].push_back(Edge(to, cap, G[to].size())); G[to].push_back(Edge(from, 0.0, G[from].size()-1));}void add_edge2(int from, int to, double cap)//建立双向边{ G[from].push_back(Edge(to, cap, G[to].size())); G[to].push_back(Edge(from, cap, G[from].size()-1));}void bfs(int s){ mem(level, -1); queue<int> que; level[s]=0; que.push(s); while(!que.empty()) { int u=que.front(); que.pop(); for(int i=0;i<G[u].size();++i) { Edge &e=G[u][i]; if(e.cap>eps && level[e.to]<0) { level[e.to]=level[u]+1; que.push(e.to); } } }}double dfs(int u, int t, double f){ if(u==t) return f; for(int &i=iter[u];i<G[u].size();++i) { Edge &e=G[u][i]; if(e.cap>0 && level[u]<level[e.to]) { double d=dfs(e.to, t, min(f, e.cap)); if(d>eps) { e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0;}double dinic(int s, int t)//最大流dinic算法{ double flow=0; while(true) { bfs(s); if(level[t]<0) return flow; mem(iter, 0); double f; while((f=dfs(s, t, INF))>eps) flow+=f; }}void init()//初始化{ V=N+2; U=E; for(int i=0;i<V;++i) { deg[i]=0; vis[i]=false; } cnt=0;}double judge(double x){ // 0 源点 // 1 ~ N 原图节点 // N+1 汇点 int s=0, t=N+1; for(int i=0;i<V;++i) G[i].clear(); for(int i=0;i<E;++i) add_edge2(edge[i].fi, edge[i].se, 1.0); for(int i=1;i<=N;++i) { add_edge1(s, i, U); add_edge1(i, t, U+2*x-deg[i]); } return (U*N-dinic(s, t))/2;}void dfs2(int u)//寻找可以通过没有满流的边到达的点{ vis[u]=true; ++cnt; for(int i=0;i<G[u].size();++i) { int v=G[u][i].to; if(!vis[v] && G[u][i].cap>0) dfs2(v); }}int main(){ while(~scanf("%d%d", &N, &E)) { if(E==0) { puts("1\n1"); continue; } init(); for(int i=0;i<E;++i) { scanf("%d%d", &edge[i].fi, &edge[i].se); ++deg[edge[i].fi]; ++deg[edge[i].se]; } double l=1.0/N, r=E/1.0, min_dif=1.0/N/N; while(r-l>=min_dif) { double mid=(l+r)/2; if(judge(mid)>eps) l=mid; else r=mid; } judge(l);//对最终结果重新建图以找到选择的点 dfs2(0); printf("%d\n", cnt-1); for(int i=1;i<=N;++i) if(vis[i]) printf("%d\n", i); } return 0;}
- poj 3155 Hard Life(最大密度子图)
- POJ 3155 Hard Life(最大密度子图)
- poj 3155 Hard Life (最大密度子图)
- POJ 3155 Hard Life(最大密度子图)
- POJ 3155 Hard Life(最大密度子图)
- poj 3155(Hard Life)分数规划/最大密度子图
- POJ 3155 Hard Life 最大密度子图
- POJ 3155 Hard Life 最大密度子图
- POJ 3155 Hard Life 最大密度子图
- 【POJ】3155 Hard Life 最大密度子图
- poj 3155 Hard Life 最大密度子图
- POJ 3155 Hard Life 最大密度子图
- poj 3155 Hard Life (最大密度子图)
- poj 3155 Hard Life 最大密度子图
- POJ 3155 Hard Life 最大密度子图
- POJ Hard Life (最大密度子图)
- poj 3155 Hard Life(01分数规划+最大流--最大密度子图)
- POJ-3155-Hard Life(最大密度子图)(01分数规划+最小割)
- linux 内核自旋锁spinlock实现详解(基于ARM处理器)
- hadoop IO操作
- tcp滑动窗口以拥塞窗口和各种缓冲的总结
- POJ3061-Subsequence
- mock数据
- POJ 3155 Hard Life(最大密度子图)
- ubuntu下 u盘的格式化
- PAT-Insertion or Heap Sort
- 1.EmBitz的安装
- 状态空间搜索
- java注解annotation
- static关键字
- 01.extern的作用
- 【51nod 教程】0-1背包问题(动态规划)