【模板】最大密度子图
ACM模板
目錄
- 概念
- 做法
- 例題
概念
選擇一個子圖G′=(V′,E′)G'=(V',E')G′=(V′,E′),其中對于任意一條邊的兩個端點必須在所選的點集中,最大化∣E′∣∣V′∣\frac{|E'|}{|V'|}∣V′∣∣E′∣?
做法
利用01分數規劃二分即最大化
∣E′∣?g∣V′∣|E'|-g|V'|∣E′∣?g∣V′∣
也就是最小化g∣V′∣?∣E′∣=∑v∈V′g?∑v∈V′1=∑v∈V′g?12(∑v∈V′dv?c[V′,V′ˉ])=12(∑v∈V′(2g?dv)+c[V′,V′ˉ])g|V'|-|E'|=\sum_{v\in V'}g-\sum_{v\in V'}1=\sum_{v\in V'}g-\frac{1}{2}(\sum_{v\in V'}d_v-c[V',\bar{V'}])=\frac 1 2(\sum_{v\in V'}(2g-d_v)+c[V',\bar{V'}])g∣V′∣?∣E′∣=v∈V′∑?g?v∈V′∑?1=v∈V′∑?g?21?(v∈V′∑?dv??c[V′,V′ˉ])=21?(v∈V′∑?(2g?dv?)+c[V′,V′ˉ])
我們發現除了割邊還有一個東西即∑v∈V′(2g?dv)\sum_{v\in V'}(2g-d_v)∑v∈V′?(2g?dv?),只需要將每個點連向匯點一條容量是2g?dv2g-d_v2g?dv?的邊即可讓構建的割的容量是上述式子。因為對于V′V'V′中的點要求與源點SSS放在一起,那么只要它與匯點存在邊就會對割的容量由貢獻。
建圖:原圖中的點與邊的容量都是1,再加上所有點向匯點連邊容量是2g?dv2g-d_v2g?dv?。
那么構建出的網絡流的割的容量c[S,T]=2(g∣V′∣?∣E′∣)c[S,T]=2(g|V'|-|E'|)c[S,T]=2(g∣V′∣?∣E′∣)
于是g∣V′∣?∣E′∣=12c[S,T]g|V'|-|E'|=\frac{1}{2}c[S,T]g∣V′∣?∣E′∣=21?c[S,T]
即求最小割。
為了防止連向匯點的邊權2g?dv2g-d_v2g?dv?是負值,需要增添一個偏移量UUU
重新建圖即:①源點向每個點連邊,容量是UUU;②原圖中的邊,容量是1;③每個點向匯點連邊,容量是2g?dv+U2g-d_v+U2g?dv?+U
可證g∣V′∣?∣E′∣=12(c[S,T]?nU)g|V'|-|E'|=\frac{1}{2}(c[S,T]-nU)g∣V′∣?∣E′∣=21?(c[S,T]?nU)
最初需要最大化的值即∣E′∣?g∣V′∣=nU?c[S,T]2|E'|-g|V'|=\frac{nU-c[S,T]}{2}∣E′∣?g∣V′∣=2nU?c[S,T]?
不難看出如果我們這里把邊看成點,選邊必須選擇兩個端點的限制可以加到邊上即邊向兩個端點連單向邊即可以轉化為最大權閉合圖問題
| 最大密度子圖 | |V| | 2|V|+|E| |
| 最大權閉合圖 | |V|+|E| | |V|+3|E| |
如果存在邊權密度:∑e∈EWe∣V∣\frac{\sum_{e\in E} W_e}{|V|}∣V∣∑e∈E?We??
dvd_vdv?記為該點出邊權值和而不是出度即可
若存在點權和邊權密度∑v∈Vpv+∑e∈EWe∣V∣\frac{\sum_{v\in V}p_v+\sum_{e\in E} W_e}{|V|}∣V∣∑v∈V?pv?+∑e∈E?We??
①dvd_vdv?記為該點出邊權值和
②連向匯點和源點的邊容量是2g?dv?2pv+U2g-d_v-2p_v+U2g?dv??2pv?+U
例題
#include<iostream> #include<algorithm> #include<cstring> using namespace std; const int N=5010,M=(50000+2*N)*2+10,INF=0x3f3f3f3f; int n,m; int h[N],e[M],ne[M],f[M],idx; int S,T,d[N],q[N],cur[N]; int deg[N],p[N]; void add(int a,int b,int c1,int c2) {e[idx]=b,ne[idx]=h[a],f[idx]=c1,h[a]=idx++;e[idx]=a,ne[idx]=h[b],f[idx]=c2,h[b]=idx++; } bool bfs() {memset(d,-1,sizeof d);int tt=0,hh=0;q[S]=0,cur[S]=h[S],d[S]=0;while(hh<=tt){int t=q[hh++];for(int i=h[t];i!=-1;i=ne[i]){int j=e[i];if(d[j]==-1&&f[i]){d[j]=d[t]+1;cur[j]=h[j];if(j==T) return 1;q[++tt]=j;}}}return 0; } int dfs(int u=S,int flow=INF) {if(u==T) return flow;int rmn=flow;for(int i=cur[u];i!=-1&&rmn;i=ne[i]){cur[u]=i;int j=e[i];if(d[j]==d[u]+1&&f[i]){int t=dfs(j,min(f[i],rmn));if(!t) d[j]=-1;f[i]-=t,f[i^1]+=t,rmn-=t;}}return flow-rmn; } int dinic() {int r=0;while(bfs()) r+=dfs();return r; } int main() {cin>>n>>m;memset(h,-1,sizeof h);S=0,T=n+1;for(int i=1;i<=n;i++) cin>>p[i],p[i]*=-1;while(m--){int a,b,c;cin>>a>>b>>c;add(a,b,c,c);deg[a]+=c,deg[b]+=c;//記錄出邊權值和}int U=0;for(int i=1;i<=n;i++) U=max(U,2*p[i]+deg[i]);for(int i=1;i<=n;i++) add(S,i,U,0),add(i,T,U-2*p[i]-deg[i],0);cout<<(U*n-dinic())/2<<'\n';return 0; }總結
以上是生活随笔為你收集整理的【模板】最大密度子图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 郁可唯个人资料 郁可唯简介
- 下一篇: 消息称索尼第三方游戏策略转变,世嘉和万代