程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ Hard Life (最大密度子圖)

POJ Hard Life (最大密度子圖)

編輯:C++入門知識

POJ Hard Life (最大密度子圖)


Hard Life

做該題前需要先了解一些專有名詞及定理。

希望你可以親自看看2007年胡伯濤的論文!

有向圖的閉合圖(closure): 閉合圖內任意點的任意後繼也一定還在閉合圖中。

題目:

給出N個人,有些人之間有聯系,而有聯系的兩個人被認為是一個整體。如果,把人看作點,把關系看作邊,則要求你求出 邊 / 點 的比值最大。而這些點邊之間必須是一個閉合圖。

算法分析:

最大密度子圖算法構造:

\

\

把原圖中的無向邊轉換成兩條有向邊,容量為1。

設一源點,連接所有點,容量為U(取m)。<喎?http://www.Bkjia.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; }


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved