ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AGC/ARC 难题集

2022-07-24 11:37:56  阅读:144  来源: 互联网

标签:难题 ch int 路径 AGC son ARC ew dp


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有