給兩個樹,大小分別為n和m,現在兩棵樹各選一些點(包括1),使得這棵樹以1號點為根同構(同構就是每個點的孩子數目相同),求最大的同構樹。(n, m<=500)
我們從兩棵樹中各取出乙個點,考慮以這兩個點為根能得到的最大同構數。
容易得到:
設\(d(i, j)\)表示第一棵樹選\(i\)號點,第二棵樹選\(j\)號點所能得到的最大同構數。
那麼\(d(i, j)\)就是等於從\(i\)這個點的子樹選一些點,從\(j\)這個點的子樹選一些點,選出的點數目相同,一一匹配,則答案就是這些點的\(\sum d(x, y)\)。
計算這個我們用最大費用流來計算。
同時我們從深度深的向深度淺的進行計算。
#include using namespace std;
const int n=505, m=n*2;
int ed[2][n][n], ecnt[2][n], n[2], ihead[m], cnt=1;
struct e e[m*m];
void add(int x, int y, int cap, int w) ; ihead[x]=cnt;
e[++cnt]=(e); ihead[y]=cnt;
}int d[m], p[m];
bool spfa(int s, int t, int n)
int y=e[i].to;
if(d[y]>d[x]+e[i].w)
else }}
} }return d[t]!=0x7f7f7f7f;
}void tadd(int x, int y, int w)
int st[2][n][n], scnt[2][n], mxdep;
void dfs(int w, int x, int f, int dep)
dfs(w, y, x, dep+1);
ed[w][x][sz++]=y;
} ecnt[w][x]=sz;
}int f[n][n];
void work(int x, int y)
for(int i=1; i<=c2; ++i)
for(int i=0; i} int &now=f[x][y];
now=1;
while(spfa(s, t, t))
}void dfs(int dep)
int c1=scnt[0][dep], c2=scnt[1][dep];
for(int i=0; i} dfs(dep-1);
}int main()
scanf("%d", &n[1]);
for(int i=1; idfs(0, 1, 0, 0);
dfs(1, 1, 0, 0);
dfs(mxdep);
printf("%d\n", f[1][1]);
return 0;
}
弱省互測 2 t3
給出 n 個01位元組和 m 個01位元組,要求用後者去匹配前者,兩個串能匹配當且僅當除了每個位元組末位不同,其他位都要相同。問匹配後者至少有多少個末位不同。1 le m le n le 2.5 times 10 5 首先我們可以用kmp計算出能匹配的位置,然後單獨考慮末位不同的情況。我們將末尾的位...
弱省互測 0 t2
給定兩個字串 a 和 b,求下面四個問題的答案 1.在 a 的子串中,不是 b 的子串的字串的數量。2.在 a 的子串中,不是 b 的子串行的字串的數量。3.在 a 的子串行中,不是 b 的子串的字串的數量。4.在 a 的子串行中,不是 b 的子串行的字串的數量。其中子串是指本質不同的子串,不同的位...
弱省互測 0 t1
給乙個 n times m 的01網格,1不能走,從起點 1,1 走到 n,m 每次只能向下或向右走一格,問兩條不相交的路徑的方案數。n,m 1000 先考慮一條,再考慮去掉相交的情況。令 d a,b,c,d 表示從 a,b 走到 c,d 一條路徑的方案數,則可以簡單得到答案 ans d 2,1,n...