题面
题解
现场得分:17/64
我菊花讨论错了,暴力不知道哪里写错了。
一点补充:
- 整个过程分成两块,前一块要注意一下你任何一次加边都必须递归。后一块真的可以随便写。
- 这道题可以用一些神奇的暴力莽过去。(O(frac{n^3}{64}))。就是直接每次加入一条边就用bitset和树剖把所有可以被拓展的点搞出来。(bitset用来框在(G)上的要求,树剖用来框在树上的要求)
代码
#include<bits/stdc++.h>
#define LL long long
#define MAXN 2010
#define MAXM 2010
using namespace std;
template<typename T>void Read(T &cn)
{
char c; int sig = 1;
while(!isdigit(c = getchar())) if(c == '-') sig = -1; cn = c-48;
while(isdigit(c = getchar())) cn = cn*10+c-48; cn*=sig;
}
template<typename T>void Write(T cn)
{
if(cn < 0) {putchar('-'); cn = 0-cn; }
int wei = 0; T cm = 0; int cx = cn%10; cn/=10;
while(cn) wei++, cm = cm*10+cn%10, cn/=10;
while(wei--) putchar(cm%10+48), cm /= 10;
putchar(cx+48);
}
template<typename T>void Max(T &cn, T cm) {cn = cn < cm ? cm : cn; }
template<typename T>void Min(T &cn, T cm) {cn = cn < cm ? cn : cm; }
struct Graph{
struct qwe{
int a,b,ne;
void mk(int cn, int cm, int cx) {a = cn; b = cm; ne = cx; }
};
qwe a[MAXM*2+1];
int alen;
int head[MAXN+1];
int n;
int t[MAXN+1][MAXN+1];
void lian(int cn, int cm) {a[++alen].mk(cn, cm, head[cn]); head[cn] = alen; }
void lian_d(int cn, int cm) {lian(cn, cm); lian(cm, cn); }
void getit() {int bx,by; Read(bx); Read(by); lian_d(bx, by); t[bx][by] = t[by][bx] = 1; }
void build(int cn) {n = cn; kong_a(); kong_t(); }
void kong_t() {for(int i = 0;i<=n;i++)for(int j = 0;j<=n;j++) t[i][j] = 0; }
void kong_a() {alen = 0; memset(head,0,sizeof(head)); }
void zheng() {kong_a(); for(int i = 1;i<=n;i++) for(int j = i+1;j<=n;j++) if(t[i][j]) lian_d(i,j); }
}G1, G2;
int n,m;
int ans;
int dfn[MAXN+1], lef[MAXN+1], shi;
int fa[MAXN+1][MAXN+1], f[MAXN+1][MAXN+1];
void dfs1(int cn, int ba, int ro)
{
fa[ro][cn] = ba; f[ro][cn] = ro;
for(int i = G1.head[cn];i;i = G1.a[i].ne) if(G1.a[i].b != ba) dfs1(G1.a[i].b, cn, ro);
}
void dfs2(int cn, int fa)
{
dfn[cn] = ++shi;
for(int i = G1.head[cn];i;i = G1.a[i].ne) if(G1.a[i].b != fa) dfs2(G1.a[i].b, cn);
lef[cn] = shi;
}
void dfs3(int cn, int cl, int cr)
{
ans++;
for(int i = G2.head[cn];i;i = G2.a[i].ne)
{
int y = G2.a[i].b;
if(cl > dfn[y] || dfn[y] > cr) continue;
dfs3(y, dfn[y], lef[y]);
}
}
void zeng(int,int);
void dfs4(int cn, int ro, int cm)
{
if(G2.t[ro][cn]) G2.t[ro][cn] = G2.t[cn][ro] = 0, zeng(cn, cm);
else {
f[ro][cn] = cm;
for(int i = G1.head[cn];i;i = G1.a[i].ne) if(G1.a[i].b != fa[ro][cn]) dfs4(G1.a[i].b, ro, cm);
}
}
void zeng(int cn, int cm)
{
if(cn == cm) return;
if(f[cn][cm] != cn) {zeng(f[cn][cm], cm); return; }
if(f[cm][cn] != cm) {zeng(f[cm][cn], cn); return; }
G2.t[cn][cm] = G2.t[cm][cn] = 1; f[cn][cm] = cm; f[cm][cn] = cn;
for(int i = G1.head[cm];i;i = G1.a[i].ne) if(G1.a[i].b != fa[cn][cm]) dfs4(G1.a[i].b, cn, cm); swap(cn, cm);
for(int i = G1.head[cm];i;i = G1.a[i].ne) if(G1.a[i].b != fa[cn][cm]) dfs4(G1.a[i].b, cn, cm);
}
void suan(int cn) {shi = 0; dfs2(cn, 0); dfs3(cn, dfn[cn], lef[cn]); ans--; }
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
Read(n); Read(m); G1.build(n); G2.build(n);
for(int i = 2;i<=n;i++) G1.getit();
for(int i = 1;i<=m;i++) G2.getit(); ans = 0; G2.kong_t();
for(int i = 1;i<=n;i++) dfs1(i, 0, i);
for(int i = 1;i<=m;i++) zeng(G2.a[i*2-1].a, G2.a[i*2-1].b); G2.zheng();
for(int i = 1;i<=n;i++) suan(i);
Write(ans/2); puts("");
return 0;
}