其他分享
首页 > 其他分享> > AGC/ARC 难题集

AGC/ARC 难题集

作者:互联网

AGC024E Sequence Growing Hard


ARC097D Monochrome Cat
开始想的是一个暴力的换根 dp 模拟题意的选择,打到一半意识到严重的问题就是代码 3K 起步且可能要调一年,所以灰溜溜去看题解了。
题解发现性质就能转化成简单问题的 dp。首先不难发现如果一个无根树的子树(意会一下)全黑就肯定不需要动它,所以从黑叶子开始 bfs 把这些坨坨都删掉,变成一棵新树。显然行走方案是:从 \(u\) 出发,走到每一个叶子,所有叶子都走到之后有两种选择,要么返回 \(u\),要么在返回 \(u\) 的路上某个点停下,如果最后一些经过的点没变成黑,就用额外使用操作 2 变成黑。于是没有走的一部分一定是一条到 \(u\) 结束的树上路径。考虑先把假设返回 \(u\) 需要多少代价算出来,再减去路径的最大返收益。由于前者其实和 \(u\) 无关,我们把它算出来,叫做 \(sum\),剩下的问题便是从树上选一条返收益最大的有向路径,其中返收益可以表示出来:
\(s\to t [len]\) 的返收益:\(len+\) 路径(except \(s\))上额外反转的点-路径(except \(s\))上未额外反转的点
至此可以使用树形 dp 解决了。

/*
dp: let f[i] denote the maximum refund for directional routes in i's subtree.
f[i][2]=max(f[i][2],f[i][1]+f[son][0]+1+ew[son]-!ew[son],f[i][0]+f[son][1]+1+ew[i]-!ew[i])
f[i][0]=max(f[i][0],f[son][0]+1+ew[son]-!ew[son])
f[i][1]=max(f[i][1],f[son][1]+1+ew[i]-!ew[i])
*/
#include <bits/stdc++.h>
using namespace std;
inline int read(){
	register char ch=getchar();register int x=0;
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
const int N=1e5+5;
int n,l=1,r,rt,sum,Edge,u[N],v[N],deg[N],col[N],f[N][3],Q[N];
bool del[N],ew[N];
char s[N];
vector<int>G[N];
void shan(){
	for(int i=1;i<=n;i++)if(deg[i]==1&&col[i])Q[++r]=i,del[i]=1;
	while(l<=r){
		int x=Q[l++];
		for(int y:G[x])if(!del[y]){
			if((--deg[y])==1&&col[y])Q[++r]=y,del[y]=1;
		}
	}
	for(int i=1;i<=n;i++)G[i].clear();
	for(int i=1;i<n;i++)if(!del[u[i]]&&!del[v[i]])
		G[u[i]].push_back(v[i]),G[v[i]].push_back(u[i]),Edge++;
	for(int i=1;i<=n;i++)if(!del[i])rt=i;
	if(!rt){puts("0");exit(0);}
}
void dfs(int x,int p){
	for(int y:G[x])if(y^p){
		dfs(y,x);
		f[x][2]=max(f[x][2],max(f[x][1]+f[y][0]+1+ew[y]-!ew[y],f[x][0]+f[y][1]+1+ew[x]-!ew[x]));
		f[x][0]=max(f[x][0],f[y][0]+1+ew[y]-!ew[y]);
		f[x][1]=max(f[x][1],f[y][1]+1+ew[x]-!ew[x]);
	}
}
int main(){
	n=read();
	for(int i=1;i<n;i++){
		u[i]=read(),v[i]=read();
		G[u[i]].push_back(v[i]),G[v[i]].push_back(u[i]);
		deg[u[i]]++,deg[v[i]]++;
	}
	scanf("%s",s+1);
	for(int i=1;i<=n;i++)col[i]=s[i]=='B';
	shan();
	sum=2*Edge;
	for(int i=1;i<=n;i++)if(!del[i]&&!((deg[i]&1)^col[i]))ew[i]=1,sum++;
	dfs(rt,0);
	int mx=0;
	for(int i=1;i<=n;i++)if(!del[i])mx=max(mx,max(f[i][2],max(f[i][1],f[i][0])));
	cout<<sum-mx<<'\n';
}

标签:难题,ch,int,路径,AGC,son,ARC,ew,dp
来源: https://www.cnblogs.com/impyl/p/agc.html