• ARC097F Monochrome Cat


    给定 (n) 个点的树,每个点有黑白色。

    猫猫可以空降在任意位置,若当前位置为 (u),可以选择以下两项之一进行:

    • 反转 (u) 的颜色。
    • 移动到相邻点 (v),反转 (v) 的颜色。

    求变为全黑的最小操作次数。(nle 10^5)


    把黑叶子删完,此时叶子都是白的,都需要经过。

    可以从某个叶子开始,依次经过每个叶子,操作次数是路径长度+中途踩一踩修整贡献。

    回路显然会把每条边经过恰好两遍,把回路的贡献算出来,去掉贡献最大的一条路径,也就是直径,用树形 dp 找出直径长度即可。

    时空复杂度 (O(n))

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100003;
    template<typename T>
    void read(T &x){
    	int ch = getchar(); x = 0; bool f = false;
    	for(;ch < '0' || ch > '9';ch = getchar()) f |= ch == '-';
    	for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
    	if(f) x = -x;
    } template<typename T>
    bool chmax(T &a, const T &b){if(a < b) return a = b, 1; return 0;}
    int n, cnt, ans, u[N], v[N], deg[N], head[N], to[N<<1], nxt[N<<1]; char str[N];
    void add(int u, int v){to[++cnt] = v; nxt[cnt] = head[u]; head[u] = cnt;}
    int q[N], fr, re, dis, val[N], dep[N]; bool vis[N];
    void dfs(int x, int f = 0){
    	for(int i = head[x];i;i = nxt[i]) if(!vis[to[i]] && to[i] != f){
    		dfs(to[i], x);
    		chmax(dis, dep[x] + dep[to[i]] + val[x]);
    		chmax(dep[x], dep[to[i]]); 
    	} dep[x] += val[x];
    }
    int main(){ //freopen("a.in", "r", stdin);
    	read(n);
    	for(int i = 1;i < n;++ i){
    		read(u[i]); read(v[i]);
    		add(u[i], v[i]); add(v[i], u[i]);
    		++ deg[u[i]]; ++ deg[v[i]];
    	} scanf("%s", str+1);
    	for(int i = 1;i <= n;++ i) if(deg[i] == 1 && str[i] == 'B') q[re++] = i;
    	while(fr < re){
    		int u = q[fr++]; vis[u] = true;
    		for(int i = head[u];i;i = nxt[i]) if(!vis[to[i]]){
    			-- deg[to[i]];
    			if(deg[to[i]] == 1 && str[to[i]] == 'B')
    				q[re++] = to[i];
    		}
    	} cnt = 0; memset(head, 0, sizeof head);
    	for(int i = 1;i < n;++ i)
    		if(!vis[u[i]] && !vis[v[i]]){
    			add(u[i], v[i]); add(v[i], u[i]);
    		} ans = cnt;
    	for(int i = 1;i <= n;++ i)
    		if(!vis[i] && (deg[i] & 1) == (str[i] == 'B')){
    			++ ans; val[i] = 2;
    		}
    	for(int i = 1;i <= n;++ i) if(!vis[i]){dfs(i); break;}
    	printf("%d
    ", ans - dis);
    }
    
  • 相关阅读:
    Java正则表达式的使用
    萤火虫小巷2(看完了)
    第七章--Java基础类库--与用户的互动
    Android界面编程--使用活动条(ActionBar)--通过ActionBar菜单改变TextView的字体和颜色
    电影:换肤(Replace)
    Android界面编程--使用活动条(ActionBar)
    萤火虫小巷1
    大三下半学期(3月4日定下的学习计划)
    12月17日问题
    JQuery 分页显示jquery-pager-1.0.js
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/14545740.html
Copyright © 2020-2023  润新知