• [POI2011]Inspekcja


    [POI2011]Inspekcja

    题目大意:

    给你一棵(n(nle10^6))个点的树,(s)为起点。每次选择一个点作为目标点(t_i),沿最短路走到(t_i)再走回(s)(最后一次除外)。相邻两次行动不能经过相同的边。问将每一个点作为(s),是否存在一种方案使得除(s)外的所有结点都作为目标点被恰好访问一次,如果是,求最小路径和。

    思路:

    存在合法方案当且仅当去掉(s)后剩下的连通块中,最大的连通块大小不超过其余连通块大小之和。

    这样的点一定是重心(反过来不一定),因此最多就不超过两个。

    答案就是以这个点为根后所有点深度和×2-最大深度。

    注意如果恰好有一个子树大小为(frac n2),则最后删掉的深度一定在这棵子树中。

    源代码:

    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<climits>
    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;
    }
    typedef long long int64;
    const int N=1e6+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 n,size[N],max[N],dep[N],far[N];
    void dfs1(const int &x,const int &par) {
    	size[x]=1;
    	for(unsigned i=0;i<e[x].size();i++) {
    		const int &y=e[x][i];
    		if(y==par) continue;
    		dfs1(y,x);
    		size[x]+=size[y];
    		max[x]=std::max(max[x],size[y]);
    	}
    	max[x]=std::max(max[x],n-size[x]);
    }
    void dfs2(const int &x,const int &par) {
    	far[x]=0;
    	size[x]=1;
    	dep[x]=dep[par]+1;
    	for(unsigned i=0;i<e[x].size();i++) {
    		const int &y=e[x][i];
    		if(y==par) continue;
    		dfs2(y,x);
    		size[x]+=size[y];
    		far[x]=std::max(far[x],far[y]+1);
    	}
    }
    int main() {
    	n=getint();
    	max[0]=n+1;
    	dep[0]=-1;
    	for(register int i=1;i<n;i++) {
    		add_edge(getint(),getint());
    	}
    	dfs1(1,0);
    	for(register int x=1;x<=n;x++) {
    		if(max[x]>n/2) {
    			puts("-1");
    			continue;
    		}
    		dfs2(x,0);
    		int max=0;
    		int64 sum=0;
    		for(register int i=1;i<=n;i++) {
    			sum+=dep[i];
    			max=std::max(max,dep[i]);
    		}
    		for(register unsigned i=0;i<e[x].size();i++) {
    			const int &y=e[x][i];
    			if(size[y]==n/2) max=far[y]+1;
    		}
    		printf("%lld
    ",sum*2-max);
    	}
    	return 0;
    }
    
  • 相关阅读:
    设备上下文相关函数 冷夜
    DirectxDraw加载位图 冷夜
    MMO游戏数值框架概述(偏模拟方向) 冷夜
    C++基本数据类型列表 冷夜
    Ryzom相关的项目简介 冷夜
    使用QueryPerformanceFrequency 计算程序执行时间 冷夜
    C和C++运算符 冷夜
    编译错误记录文档 冷夜
    ANSI编码对比表 冷夜
    mscorsvw.exe是什么 冷夜
  • 原文地址:https://www.cnblogs.com/skylee03/p/9794531.html
Copyright © 2020-2023  润新知