topcoder 12543 DeerInZooDivOne
给出一个 \(n\) 个节点的树,求出两个极大的不相交的同构联通子图的大小.
\(1\leq n\leq 50\)
首先要保证不相交,考虑断掉一条边,两个联通子图在两边,再考虑在断开的两个树中找到根节点 \(r_1\) 和 \(r_2\),然后树形 \(dp\) ,考虑 \(dp(x,y)\) 为第一个树上选节点 \(x\) ,第二个树上选节点 \(y\) 的最大联通子图大小,问题就出在树形 \(dp\) 的转移,要考虑儿子节点之间的 \(dp\) 匹配,这个问题可以用最小费用流 .
考虑 \(S\) 向每一个 \(x\) 的儿子节点连边 \((1,0)\) ,\(y\) 的每个儿子节点向 \(T\) 连边 \((1,0)\) ,\(x\) 的儿子节点 \(x'\) 向 \(y\) 的儿子节点连边 \((1,-dp(x',y'))\)
得到的代价取反 \(+1\) 即为 \(dp(x,y)\) .
时间复杂度 : \(O(n^6)\)
空间复杂度 : \(O(n^2)\)
code
#include<bits/stdc++.h>
using namespace std;
const int N=55;
class MaxFlow{
public:
class edge{public:int to,nxt,cap,w;}e[(N*N)<<1];
int cnt=0;
int hd[N],dis[N],flw[N],pe[N],px[N];
bool vis[N];
queue<int>Q;
inline void init(){cnt=0;memset(hd,-1,sizeof(hd));}
inline void ae(int u,int v,int cap,int w){
e[cnt]=(edge){v,hd[u],cap,w};hd[u]=cnt++;
e[cnt]=(edge){u,hd[v],0,-w};hd[v]=cnt++;
}
bool spfa(int s,int t){
memset(dis,0x3f3f3f3f,sizeof(dis));
memset(flw,0x3f3f3f3f,sizeof(flw));
memset(vis,0,sizeof(vis));
px[t]=-1;dis[s]=0;vis[s]=true;Q.push(s);
while(!Q.empty()){
int x=Q.front();vis[x]=false;Q.pop();
for(int i=hd[x];i!=-1;i=e[i].nxt){
if(e[i].cap&&dis[e[i].to]>dis[x]+e[i].w){
dis[e[i].to]=dis[x]+e[i].w;
flw[e[i].to]=min(flw[x],e[i].cap);
px[e[i].to]=x;pe[e[i].to]=i;
if(!vis[e[i].to])vis[e[i].to]=true,Q.push(e[i].to);
}
}
}
return px[t]!=-1;
}
int mcf(int s,int t){
int res=0;
while(spfa(s,t)){
res+=dis[t]*flw[t];
for(int x=t;x!=s;x=px[x])e[pe[x]].cap-=flw[t],e[pe[x]^1].cap+=flw[t];
}
return -res;
}
}F;
class DeerInZooDivOne{
public:
int n;
vector<int>g[N],e[N];
vector<int>vec[2],dvec[2];
bool col[N];
int dp[N][N];
void dfs(int x,int fa,int c){
col[x]=c;vec[c].push_back(x);
for(auto to:e[x]){
if(to==fa)continue;
dfs(to,x,c);
}
}
void dfs(int x,int fa){
for(auto to:e[x]){
if(to==fa||col[to]!=col[x])continue;
dfs(to,x);
g[x].push_back(to);
}
dvec[col[x]].push_back(x);
}
int solve(int x,int y){
for(int i=0;i<n;i++)g[i].clear();
dvec[0].clear();dvec[1].clear();
memset(dp,0,sizeof(dp));
dfs(x,-1);
dfs(y,-1);
for(auto p:dvec[0])for(auto q:dvec[1]){
F.init();
int S=n,T=n+1;
for(auto sp:g[p])F.ae(S,sp,1,0);
for(auto sq:g[q])F.ae(sq,T,1,0);
for(auto sp:g[p])for(auto sq:g[q])F.ae(sp,sq,1,-dp[sp][sq]);
dp[p][q]=F.mcf(S,T)+1;
}
return dp[x][y];
}
int getmax(vector<int>a,vector<int>b){
n=(int)a.size()+1;
for(int i=0;i<n-1;i++){
e[a[i]].push_back(b[i]);
e[b[i]].push_back(a[i]);
}
int ans=0;
for(int i=0;i<n-1;i++){
int u=a[i],v=b[i];
vec[0].clear();
vec[1].clear();
dfs(u,v,0);
dfs(v,u,1);
for(auto x:vec[0])for(auto y:vec[1])ans=max(ans,solve(x,y));
}
return ans;
}
}test;

浙公网安备 33010602011771号