[POJ3155]Hard Life
试题描述
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.
输入
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.
输出
输入示例
5 61 55 44 22 51 23 1
输出示例
41245
数据规模及约定
见“输入”
题解
调了一整天。。。。。
原因就在于最后输出方案是找哪些点属于 S 割的时候不能简单地看最后一层边是否被割掉了,而是要 dfs 一波。。。。。
这题就是求最大密度子图。
分数规划,二分答案 x,然后我们要找到是否存在一种方案使得 |E| - |V|·x > 0(E 指边集,V 指点集),所以我们要最大化 |E| - |V|·x,我们发现如果选一条边,就必须选它两个端点,这时我们把边也看成一个权为 1 的点,把原图的点看成权为 -x 的点,然后就是求最大权闭合子图了。
网络流构图:源点向边所代表的点连容量为 1 的边,边所代表的点向边的两个端点连容量无穷的边,剩余点向汇点连容量为 x 的边,最大的 |E| - |V|·x = m - 最小割。
#include#include #include #include #include #include #include using namespace std;int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); } return x * f;}#define maxN 1110#define maxM 6210#define maxn 110#define maxm 1010#define eps 1e-8#define oo 1e10struct Edge { int from, to; double flow; Edge() {} Edge(int _1, int _2, double _3): from(_1), to(_2), flow(_3) {}};struct Dinic { int n, m, s, t, head[maxN], nxt[maxM]; Edge es[maxM]; int Q[maxN], hd, tl, vis[maxN]; int cur[maxN]; bool scut[maxN]; void init() { m = 0; memset(head, -1, sizeof(head)); return ; } void setn(int _n) { n = _n; return ; } void AddEdge(int a, int b, double c) { es[m] = Edge(a, b, c); nxt[m] = head[a]; head[a] = m++; es[m] = Edge(b, a, 0); nxt[m] = head[b]; head[b] = m++; return ; } bool BFS() { memset(vis, 0, sizeof(vis)); vis[s] = 1; hd = tl = 0; Q[++tl] = s; while(hd < tl) { int u = Q[++hd]; for(int i = head[u]; i != -1; i = nxt[i]) { Edge& e = es[i]; if(!vis[e.to] && fabs(e.flow) > eps) { vis[e.to] = vis[u] + 1; Q[++tl] = e.to; } } } return vis[t] > 1; } double DFS(int u, double a) { if(u == t || !a) return a; double flow = 0, f; for(int& i = cur[u]; i != -1; i = nxt[i]) { Edge& e = es[i]; if(vis[e.to] == vis[u] + 1 && (f = DFS(e.to, min(a, e.flow)))) { flow += f; a -= f; e.flow -= f; es[i^1].flow += f; if(!a) return flow; } } return flow; } double MaxFlow(int _s, int _t) { s = _s; t = _t; double flow = 0; while(BFS()) { for(int i = 1; i <= n; i++) cur[i] = head[i]; flow += DFS(s, oo); } return flow; } void dfs(int u) { scut[u] = 1; for(int i = head[u]; i != -1; i = nxt[i]) { Edge& e = es[i]; if(es[i^1].flow > eps && !scut[e.to]) scut[e.to] = 1, dfs(e.to); } return ; }} sol;int CntP;struct Point { int id; Point(): id(0) {} int p() { return id ? id : id = ++CntP; }} ess[maxm], pss[maxn], Source, Tank;int main() { sol.init(); int n = read(), m = read(), M; if(!m) return puts("1\n1"), 0; for(int i = 1; i <= m; i++) { int a = read(), b = read(); sol.AddEdge(ess[i].p(), pss[a].p(), oo); sol.AddEdge(ess[i].p(), pss[b].p(), oo); sol.AddEdge(Source.p(), ess[i].p(), 1); } M = sol.m; for(int i = 1; i <= n; i++) sol.AddEdge(pss[i].p(), Tank.p(), 0); sol.setn(CntP); double l = 0, r = m + 1; while(r - l > eps) { double mid = (l + r) / 2; for(int i = 0; i < M; i += 2) sol.es[i].flow += sol.es[i^1].flow, sol.es[i^1].flow = 0; for(int i = M; i < sol.m; i += 2) sol.es[i].flow = mid, sol.es[i^1].flow = 0; if((double)m - sol.MaxFlow(Source.p(), Tank.p()) > eps) l = mid; else r = mid; } for(int i = 0; i < M; i += 2) sol.es[i].flow += sol.es[i^1].flow, sol.es[i^1].flow = 0; for(int i = M; i < sol.m; i += 2) sol.es[i].flow = l, sol.es[i^1].flow = 0; sol.MaxFlow(Source.p(), Tank.p()); sol.dfs(Tank.p()); int cnta = 0; for(int i = 1; i <= n; i++) cnta += !sol.scut[pss[i].p()]; printf("%d\n", cnta); for(int i = 1; i <= n; i++) if(!sol.scut[pss[i].p()]) printf("%d\n", i); return 0;}