博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[POJ3155]Hard Life
阅读量:5052 次
发布时间:2019-06-12

本文共 5354 字,大约阅读时间需要 17 分钟。

[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 54. If we add person number 3 to the team then hardness factor decreases to 65.

输入

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 ≤ aibi ≤ nai ≠ bi) on a line. The order of people in a pair is arbitrary and no pair is listed twice.

输出

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.

输入示例

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;}

 

转载于:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6875806.html

你可能感兴趣的文章
linux调度器系列
查看>>
mysqladmin
查看>>
解决 No Entity Framework provider found for the ADO.NET provider
查看>>
SVN服务器搭建和使用(三)(转载)
查看>>
Android 自定义View (三) 圆环交替 等待效果
查看>>
设置虚拟机虚拟机中fedora上网配置-bridge连接方式(图解)
查看>>
HEVC播放器出炉,迅雷看看支持H.265
查看>>
[置顶] Android仿人人客户端(v5.7.1)——人人授权访问界面
查看>>
Eclipse 调试的时候Tomcat报错启动不了
查看>>
【安卓5】高级控件——拖动条SeekBar
查看>>
ES6内置方法find 和 filter的区别在哪
查看>>
Android入门之文件系统操作(二)文件操作相关指令
查看>>
Android实现 ScrollView + ListView无滚动条滚动
查看>>
Swift 中的指针使用
查看>>
Swift - 使用闭包筛选过滤数据元素
查看>>
alue of type java.lang.String cannot be converted to JSONObject
查看>>
搜索引擎选择: Elasticsearch与Solr
查看>>
JAVA设计模式之简单工厂模式与工厂方法模式
查看>>
③面向对象程序设计——封装
查看>>
【19】AngularJS 应用
查看>>