【POJ3155】生活的艰辛Hard Life
题面
Description
ADN公司内部共 n个员工,员工之间可能曾经因为小事有了过节,总是闹矛盾。若员工u和员工 v有矛盾,用边(u, v)表示,共 m个矛盾。最近,ADN公司内部越来越不团结,Amber决定裁员。Amber想得到一个被裁人员的清单,使得被裁人员间的不团结率最高。不团结率定义为被裁人员间的矛盾总数与被裁人员数的比值(不团结率=被裁人员之间的矛盾总数/被裁人员数)。
在上图这个例子中1, 2, 4和5,4个人中都有5对矛盾,则不团结率为\(\frac 45\)。如果我们添加3到这个团队,则不团结率就下降到\(\frac 56\)。
Input
输入文件的第一行包含两个整数n和m (1≤n≤100,0≤m≤1000),n表示公司的总人数(编号从1到n),m表示矛盾的对数。
接下来m行,每行两个整数ai和bi(1≤ai,bi≤n,ai≠bi),描述一对矛盾,每对矛盾只会出现一次。
Output
输出文件的第一行为一个整数k(1≤k≤n),表示最不团结的团队总人数。
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
sample output #2
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.
题目分析
最大密度子图模板题。
假设答案为\(k\) ,则要求解的问题是:
选出一个合适的点集 \(V\) 和边集 \(E\),令\((|E|−k∗|V|)\)取得最大值。
所谓“合适”是指满足如下限制:若选择某条边,则必选择其两端点。
建图:
以原图的边作为左侧顶点,权值为\(1\);
原图的点作为右侧顶点,权值为\(+k\)。
若原图中存在边 \((u,v)\),则新图中添加两条边 \(([uv]−>u),([uv]−>v)\),转换为最大权闭合子图。
代码实现
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#define MAXN 0x7fffffff
#define eps 1e-9
typedef long long LL;
const int N=1105;
using namespace std;
inline int Getint(){register int x=0,f=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;}
int n,m,S,T,num;
struct node{int next,to,pair;double flow;}g[N<<3];
struct Edge{int x,y;}s[N];
int h[N],cnt;
void AddEdge(int x,int y,double z){
g[++cnt].to=y,g[cnt].next=h[x],h[x]=cnt,g[cnt].flow=z,g[cnt].pair=cnt+1;
g[++cnt].to=x,g[cnt].next=h[y],h[y]=cnt,g[cnt].flow=0,g[cnt].pair=cnt-1;
}
int GAP[N],dis[N];
void Init(){
static int q[N];
fill(dis,dis+num,0),fill(GAP,GAP+num,0);
int l=0,r=1;q[++l]=T,++GAP[dis[T]=1];
while(l<=r){
int x=q[l++];
for(int i=h[x];i;i=g[i].next){
int to=g[i].to;
if(!dis[to])++GAP[dis[to]=dis[x]+1],q[++r]=to;
}
}
}
double Dfs(int x,double Maxf){
if(x==T||!Maxf)return Maxf;
double ret=0;
for(int i=h[x];i;i=g[i].next){
int to=g[i].to;
if(g[i].flow&&dis[x]==dis[to]+1){
double dlt=Dfs(to,min(g[i].flow,Maxf-ret));
g[i].flow-=dlt;
g[g[i].pair].flow+=dlt;
ret+=dlt;
if(dis[S]==num+1||ret+eps>=Maxf)return ret;
}
}
if(!(--GAP[dis[x]]))dis[S]=num+1;
else GAP[++dis[x]]++;
return ret;
}
double SAP(){
Init();
double ans=Dfs(S,MAXN);
while(dis[S]<=num)ans+=Dfs(S,MAXN);
return ans;
}
bool Check(double mid){
fill(h,h+num,0),cnt=0;
for(int i=1;i<=m;i++)AddEdge(S,i,1),AddEdge(i,s[i].x+m,MAXN),AddEdge(i,s[i].y+m,MAXN);
for(int i=1;i<=n;i++)AddEdge(i+m,T,mid);
return m-SAP()>0;
}
int ans;bool vis[N];
void Find(int x){
ans+=(x>m&&x<=m+n);
vis[x]=1;
for(int i=h[x];i;i=g[i].next){
int to=g[i].to;
if(g[i].flow&&!vis[to])Find(to);
}
}
int main(){
n=Getint(),m=Getint(),S=0,T=n+m+1,num=T+1;
if(!m)cout<<1,exit(0);
for(int i=1;i<=m;i++)s[i].x=Getint(),s[i].y=Getint();
double l=0,r=m,Eps=1.0/n/n;
while(l+Eps<r){
double mid=(l+r)/2;
if(Check(mid))l=mid;
else r=mid;
}
Check(l),Find(S);
cout<<ans;
return 0;
}
【POJ3155】生活的艰辛Hard Life的更多相关文章
- 这些年正Android - 大学
还记得,第一次看见小周是在大一的操场上. 她正向教学楼站着,一身白配粉的休闲上衣搭配湖蓝色的牛仔裤,穿着一双很平凡的凉鞋,手里拿着当年的Nokia 3110c,皙清的手指,素颜的站着不言不笑.现在回 ...
- python 爬取腾讯微博并生成词云
本文以延参法师的腾讯微博为例进行爬取并分析 ,话不多说 直接附上源代码.其中有比较详细的注释. 需要用到的包有 BeautifulSoup WordCloud jieba # coding:utf-8 ...
- 2018(上)C高级第0次作业
一:已关注邹欣老师的博客,以及一些任课老师的博客. 二:新学期新气象,走过基础C语言的学习,转眼间来到了C语言的高级学习... 1.翻阅邹欣老师博客关于师生关系博客,并回答下列问题. (1)最理想的师 ...
- 记一次重大生产事故,在那 0.1s 我想辞职不干了!
一.发生了什么? 1.那是一个阳光明媚的下午,老婆和她的闺蜜正在美丽的湖边公园闲逛(我是拎包拍照的). 2.突然接到甲方运营小妹的微信:有个顾客线上付款了,但是没有到账,后台卡在微信支付成功(正常状态 ...
- 【8.28校内测试】【区间DP】
感受到了生活的艰辛QAQ...这才是真正的爆锤啊...(因为t1t3还没有理解所以只能贴t2叻QAQ 区间DP...爆哭把题理解错了,以为随着拿的东西越来越多,断点也会越来越多,出现可以选很多的情况Q ...
- HDU2191悼念512汶川大地震遇难同胞——珍惜现在,感恩生活[多重背包]
悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav ...
- hdu 2191 多重背包 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
http://acm.hdu.edu.cn/showproblem.php?pid=2191 New~ 欢迎“热爱编程”的高考少年——报考杭州电子科技大学计算机学院关于2015年杭电ACM暑期集训队的 ...
- ACM生活总结
两年ACM生活总结 转眼已经踏入ACM这条不归路已经两年了, 深深的感觉到ACM的不易 和 艰辛,但同时ACM给我所带来的快乐,让我认为值一切都是值得的. 我刚上大学那会,我们学校的ACM刚刚起步不到 ...
- 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 分类: dp 2015-05-21 10:50 14人阅读 评论(0) 收藏
Description 急!灾区的食物依然短缺! 为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并 ...
随机推荐
- fragment中的onCreateView和onViewCreated的区别和
(1) onViewCreated在onCreateView执行完后立即执行. (2) onCreateView返回的就是fragment要显示的view.
- nginx信号及平滑升级
1.nginx信号 nginx进程处理命令: kill -signals PID PID即nginx进程ID signals的参数解释如下所示: TERM,INT快速关闭进程 QUIT优雅的关闭,如果 ...
- 【转载】网易极客战记官方攻略-地牢-严酷考验 B
关卡连接:https://codecombat.163.com/play/level/the-gauntlet-b 免费试玩:https://codecombat.163.com/play 使用你的所 ...
- 封装加减乘除函数 解决JS 浮点数计算 Bug
计算机内部的信息都是由二进制方式表示的,即0和1组成的各种编码,但由于某些浮点数没办法用二进制准确的表示出来,也就带来了一系列精度问题.当然这也不是JS独有的问题. 例如, 我们在用JS做浮点运算会遇 ...
- 项目实战 - 混合式App开发
为何要使用混合式开发? 要说为什么使用Hybrid App [混合式开发],就要先了解什么是Native App[原生程序], Web App[网站程序]. Native App 是专门针对某一类移动 ...
- JavaIO流之字节流
什么是字节? 所谓字节(Byte),是计算机数据存储的一种计量单位.一个二进制位称为比特(bit),8个比特组成一个字节,也就是说一个字节可以用于区分256个整数(0~255).由此我们可以知道,字节 ...
- Stream(Java 8)
Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作(aggregate operation),或者大批量数据操作 (b ...
- SQL LIKE 运算符
SQL LIKE 运算符 在WHERE子句中使用LIKE运算符来搜索列中的指定模式. SQL LIKE 操作符 LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式. 有两个通配符与LIKE运 ...
- thinkphp 图形处理
使用Think\Image类进行图像处理功能,支持Gd库和Imagick库,包括对GIf图像处理的支持. 实例化类库 $image = new \Think\Image(); 默认使用GD库进行图像操 ...
- Shiro学习(3)授权
授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作等).在授权中需了解的几个关键对象:主体(Subject).资源(Resource).权限(Permission).角 ...