设为首页 加入收藏

TOP

POJ Hard Life (最大密度子图)
2015-07-20 17:33:08 来源: 作者: 【 】 浏览:2
Tags:POJ Hard Life 最大 密度

Hard Life

做该题前需要先了解一些专有名词及定理。

希望你可以亲自看看2007年胡伯涛的论文!

有向图的闭合图(closure): 闭合图内任意点的任意后继也一定还在闭合图中。

题目:

给出N个人,有些人之间有联系,而有联系的两个人被认为是一个整体。如果,把人看作点,把关系看作边,则要求你求出 边 / 点 的比值最大。而这些点边之间必须是一个闭合图。

算法分析:

最大密度子图算法构造:

\

\

把原图中的无向边转换成两条有向边,容量为1。

设一源点,连接所有点,容量为U(取m)。<??http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+yejSu7vjteOjrMv509C148GsvdO747Xjo6zI3cG/zqogVSYjNDM7MmctZHYgoaM8L3A+CjxwPrb+t9bDtr7Z1+6088Pctshno6zG5NbQZHbOqna1xLbIoaM8L3A+CjxwPsXQts8oVSpuLU1heEZsb3cpLzIuPj0woaM8L3A+CjxwPtfuuvPM+LP2tcRMvs3Kx9futPPD3LbIoaM8L3A+CjxwPsTD1eK49kzU2dbY0MK9qM28o6zH89futPPB96GjPC9wPgo8cD7Iu7rztNNzs/a3omJmc7vy1d9kZnOjrNffstDB9Mjdwb+089PaMLXEsd+jrMv509DE3LW9tO+1xLXjvs3Kx7TwsLihozwvcD4KPHByZSBjbGFzcz0="brush:java;">#include #include #include #include #include #include #include using namespace std; typedef pair pii; const double INF = 1e7; const double EPS = 1e-7; const int MAXN = 100 + 10; struct Edge{ int from,to; double cap,flow; Edge(){}; Edge(int _from,int _to,double _cap,double _flow) :from(_from),to(_to),cap(_cap),flow(_flow){}; }; pii verter[1010]; vector edges; vector G[MAXN]; int d[MAXN],cur[MAXN]; bool vst[MAXN]; int dv[MAXN]; int V,E,S,T; int num; void clr(){ for(int i = 0;i <= T;++i) G[i].clear(); edges.clear(); } void addEdge(int f,int t,double w){ edges.push_back(Edge(f,t,w,0.0)); edges.push_back(Edge(t,f,0.0,0.0)); int sz = edges.size(); G[f].push_back(sz - 2); G[t].push_back(sz - 1); } bool BFS(){ memset(vst,0,sizeof(vst)); queue Q; Q.push(S); d[S] = 0; vst[S] = 1; while(!Q.empty()){ int x = Q.front(); Q.pop(); for(int i = 0;i < (int)G[x].size();++i){ Edge& e = edges[G[x][i]]; if(!vst[e.to] && e.cap > e.flow){ vst[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vst[T]; } double DFS(int x,double a){ if(x == T||a == 0) return a; double flow = 0,f; for(int& i = cur[x];i < (int)G[x].size();++i){ Edge& e = edges[G[x][i]]; if(d[x] + 1 == d[e.to] && (f = DFS(e.to,min(a,e.cap - e.flow))) > 0){ e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } double maxFlow(){ double flow = 0; while(BFS()){ memset(cur,0,sizeof(cur)); flow += DFS(S,INF); } return flow; } void build(double g){ clr(); for(int i = 0;i < E;++i){ addEdge(verter[i].first,verter[i].second,1.0); addEdge(verter[i].second,verter[i].first,1.0); } for(int i = 1;i <= V;++i){ addEdge(S,i,E*1.0); addEdge(i,T,(1.0*E + 2.0 * g - dv[i])); } } //查找割边 void dfs(int u){ vst[u] = 1; if(u <= V) num++; for(int i = 0;i < (int)G[u].size();++i){ Edge& e = edges[G[u][i]]; if(!vst[e.to] && e.cap > e.flow){ dfs(e.to); } } } void solve(){ double c,lb = 0,ub = E*1.0; for(int k = 0;k < 100;++k){ double mid = (lb + ub) / 2.0; build(mid); c = maxFlow(); c = (E * V * 1.0 - c) / 2.0; if(c > EPS){ lb = mid; } else { ub = mid; } } build(lb); maxFlow(); memset(vst,0,sizeof(vst)); num = 0; dfs(S); printf("%d\n",num); for(int i = 1;i <= V;++i){ if(vst[i]) printf("%d\n",i); } } int main() { // freopen("Input.txt","r",stdin); // freopen("Output.txt","w",stdout); while(~scanf("%d%d",&V,&E)){ int a,b; if(E == 0){ printf("1\n1\n"); continue; } S = V + 1; T = V + 2; memset(dv,0,sizeof(dv)); for(int i = 0;i < E;++i){ scanf("%d%d",&a,&b); verter[i] = make_pair(a,b); dv[a]++; dv[b]++; } solve(); } return 0; }


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇uva live 6190 Beautiful Spacing.. 下一篇hdu1255 线段树+扫描线+离散化

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·JAVA现在的就业环境 (2025-12-26 01:19:24)
·最好的java反编译工 (2025-12-26 01:19:21)
·预测一下2025年Java (2025-12-26 01:19:19)
·Libevent C++ 高并发 (2025-12-26 00:49:30)
·C++ dll 设计接口时 (2025-12-26 00:49:28)