POJ 3155 最大密度子图
来源:互联网 发布:社交网络红包广告 编辑:程序博客网 时间:2024/05/23 21:33
poj3155 最大密度子图 分数规划题意:给定一个无向图,选取一个密度最大的子图,就是边数/点数的比值最大,输出子图顶点,设wi为子图边数,vi是子图点数,就是要max{wi-ans*vi}ans为二分的值,按边来考虑,如果选了一条边那么他连的两个端点都要被选,也就是边也看做是点,点权为1,原来的点点权为-ans,求最大权闭合图就可以max这个值,然后类似最优比率生成树的二分下去(这是讲解)/*主算法:零一规划,用二分来猜测最大密度为g。。。构造函数h(g)=(|E'|-g*|V'|)设D为最优解,当h(g)<0,g>D;当h(g)=0,g=D;当h(g)>0,g<D;网络流建图部分:在原图点集V 的基础上增加源S和汇T;将每条原无向边(u,v)替换为两条容量为1 的有向边(u,v)和(v,u);增加连接源S到原图每个点v的有向边(s,v) , 容量为U ;增加连接原图每个点v 到汇T 的有向边(v,T),容量为(U+2*g-dv) ,其中dv为点v的度。其中U为为了流量不出现负值而统一加的一个大数,取U=m即可。到此有h(g)=(U*n-c[S,T])/2;[S,T]为最小割。推算过程见胡伯涛论文~*/#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define maxn 308 #define edge 20800 #define inf 0x3f3f3f3f #define eps 1e-5 int first[maxn],dis[maxn],num[maxn],du[maxn]; int vv[edge],nxt[edge]; double ww[edge]; bool vis[maxn]; int e,NN,n,m; int sum = 0; int ta[2000],tb[2000]; struct Edge { int u,v; Edge(){} Edge(int uu,int vv) { u = uu;v = vv; } }; void addedge(int u,int v,double w)//添加单向边 { vv[e] = v; ww[e] = w; nxt[e] = first[u]; first[u] = e++; vv[e] = u; ww[e] = 0; nxt[e] = first[v]; first[v] = e++; } void addEdge(int u,int v,double w)//添加双向边 { vv[e] = v; ww[e] = w; nxt[e] = first[u]; first[u] = e++; vv[e] = u; ww[e] = w; nxt[e] = first[v]; first[v] = e++; } inline double min(double a,double b) { return a>b?b:a; } double dfs(int u,int s,int d,double cost) { if(u == d) return cost; double ans = 0; int _min = NN; for(int i = first[u];i != -1;i = nxt[i]) { int v = vv[i]; if(ww[i] > eps) { if(dis[v] + 1 == dis[u]) { double t = dfs(v,s,d,min(ww[i],cost)); ww[i] -= t; ww[i^1] += t; ans += t; cost -= t; if(dis[s] == NN) return ans; if(cost <= eps) break; } if(_min > dis[v]) _min = dis[v]; } } if(ans <= eps) { if(--num[dis[u]] == 0) dis[s] = NN; dis[u] = _min + 1; ++num[dis[u]]; } return ans; } double isap(int s,int d) { memset(dis,0,sizeof(dis)); memset(num,0,sizeof(num)); num[0] = NN; double ans = 0; while(dis[s] < NN) ans += dfs(s,s,d,inf); return ans; } void build(double g) { e = 0;NN = n + 2; memset(first,-1,sizeof(first)); for(int i = 1;i <= n;i++) { addedge(0,i,m); } for(int i = 1;i <= m;i++) { addEdge(ta[i],tb[i],1); } for(int i = 1;i <= n;i++) { addedge(i,n+1,m+2*g-du[i]); } } void dfs(int u) { vis[u] = 1; for(int i = first[u];i != -1;i = nxt[i]) { int v = vv[i]; if(ww[i] > 0 && !vis[v]) { vis[v] = 1; sum++; dfs(v); } } } int main() { //freopen("in.txt","r",stdin); while(scanf("%d%d",&n,&m)==2) { if(m == 0) { printf("%d\n%d\n",1,1); continue; } memset(du,0,sizeof(du)); for(int i = 1;i <= m;i++) { scanf("%d%d",&ta[i],&tb[i]); du[ta[i]]++;du[tb[i]]++; } double l = 0,r = m; while(r - l >= 1./n/n) { double mid = (l + r)/2; build(mid); if((m*n - isap(0,n+1))/2 > eps) { l = mid; } else r = mid; } build(l); memset(vis,0,sizeof(vis)); isap(0,n+1); sum = 0; dfs(0); int ok = 0; printf("%d\n",sum); for(int i = 1;i <= n;i++) { if(vis[i]) { printf("%d\n",i); } } } return 0; }
0 0
- poj 3155 (最大密度子图)
- POJ 3155 最大密度子图
- POJ 3155 最大密度子图
- poj 3155 01规划->最大密度密度子图->最大流
- poj 3155(Hard Life)分数规划/最大密度子图
- POJ 3155 Hard Life 最大密度子图
- POJ 3155 最大密度子图 二分+最小割
- 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(最大密度子图)
- sqlmap基本用法
- LeetCode的medium题集合(C++实现)四
- POJ 2987 最大权闭合图
- WinForm 无边框窗口 拖动实现
- (MySQL笔记)MySQL表达式
- POJ 3155 最大密度子图
- splint的学习与使用
- java基础——集合框架(Collections、Arrays)
- rsync 同步备份工具
- Jquery attr("checked") 返回checked或undefined 获取选中失效
- Linux中fork()函数详解 父子进程变量的关系
- 一致性hash算法(二)
- NSString属性什么时候用copy,什么时候用strong?
- 一个简单的C++程序