• [六省联考2017]摧毁“树状图”


    [六省联考2017]摧毁“树状图”

    题目大意:

    给你一个(n(nle5 imes10^5))个点的图,从图中选两条链,删掉链上所有点以及所有相连的边,使得剩下的连通块数目最多,求连通块个数。

    思路:

    树形DP。

    • f[x][0]:穿过(x)向上的半条链
    • f[x][1]:不穿过(x)且完全在子树内的一条链
    • f[x][2]:穿过(x)且完全在子树内的一条链
    • f[x][3]:穿过(x)向上的半条连以及完全在子树内的一条链

    然后就是各种大力讨论。

    这个有图示的题解比较好懂。

    源代码:

    #include<cstdio>
    #include<cctype>
    #include<vector>
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    const int N=5e5+1;
    std::vector<int> e[N];
    inline void add_edge(const int &u,const int &v) {
    	e[u].push_back(v);
    	e[v].push_back(u);
    }
    int f[N][4],ans;
    inline void upd(int &a,const int &b) {
    	a=std::max(a,b);
    }
    void dfs(const int &x,const int &par) {
    	const bool isrt=x==1;
    	const int deg=e[x].size()-!isrt;
    	f[x][0]=f[x][2]=f[x][3]=deg;
    	f[x][1]=1;
    	int max=0;
    	for(unsigned i=0;i<e[x].size();i++) {
    		const int &y=e[x][i];
    		if(y==par) continue;
    		dfs(y,x);
    		upd(ans,f[x][0]+f[y][3]-isrt);
    		upd(ans,f[x][3]+f[y][0]-isrt);
    		upd(ans,f[x][1]+f[y][1]-1);
    		upd(ans,f[x][1]+f[y][2]);
    		upd(ans,f[x][2]+f[y][1]-isrt);
    		upd(ans,f[x][2]+f[y][2]-isrt);
    		upd(f[x][1],f[y][1]);
    		upd(f[x][1],f[y][2]+1);
    		upd(f[x][3],f[y][3]+deg-1);
    		upd(f[x][3],f[y][0]+max+deg-2);
    		upd(f[x][3],f[x][0]+f[y][1]-1);
    		upd(f[x][3],f[x][0]+f[y][2]-1);
    		upd(f[x][3],f[x][2]+f[y][0]-1);
    		upd(f[x][2],f[x][0]+f[y][0]-1);
    		upd(f[x][0],f[y][0]+deg-1);
    		upd(f[x][2],f[x][0]);
    		upd(f[x][3],f[x][2]);
    		upd(max,f[y][1]);
    		upd(max,f[y][2]);
    	}
    }
    int main() {
    	const int T=getint(),x=getint();
    	for(register int i=0;i<T;i++) {
    		const int n=getint();
    		for(register int i=0;i<x*2;i++) getint();
    		for(register int i=1;i<n;i++) {
    			add_edge(getint(),getint());
    		}
    		ans=0;
    		dfs(1,0);
    		printf("%d
    ",ans);
    		for(register int i=1;i<=n;i++) {
    			e[i].clear();
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    支持向量机(SVM)相关免费学习视频集锦
    《量化投资:以MATLAB为工具》连载(2)基础篇-N分钟学会MATLAB(中)
    《量化投资:以MATLAB为工具》连载(1)基础篇-N分钟学会MATLAB(上)
    OpenCV 轮廓基本特征
    !!破解灯塔线取点与画线的“难点”
    理工科应该的知道的C/C++数学计算库(转)
    521. 最长特殊序列 Ⅰ
    520. 检测大写字母
    459. 重复的子字符串
    443. 压缩字符串
  • 原文地址:https://www.cnblogs.com/skylee03/p/9770455.html
Copyright © 2020-2023  润新知