【日常训练】20200608_解谜_AGC033F Add Edges_转化问题/思维

题面

题解

现场得分: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;
}
原文地址:https://www.cnblogs.com/czyarl/p/13067063.html