zoukankan      html  css  js  c++  java
  • Tinkoff Internship Warmup Round 2018 and Codeforces Round #475 (Div. 1) 963B 964D B Destruction of a Tree

      OvO http://codeforces.com/contest/963/problem/B

      CF 963B 964D

      对于题目要求,显然一开始的树,要求度数为偶数的节点个数为奇数个,通过奇偶讨论显然这个树总节点个数为奇数个

      然后对于每一步分割出来的树林,显然树林中每个树都得满足度数为偶数的节点个数为奇数个,同样地,可以得到树林中每个树的总结点为奇数个

      其实上面写的一些是废话,后文并不会用到……

      首先排除度数为偶数的节点有偶数个的树,即已知要讨论的树均满足度数为偶数的节点有奇数个

      从叶子节点往上搜(采用回溯),搜到第一个度数为偶数的节点 X,那么以 X 为根的子树中,必然只有这个根节点 X 的度数为偶数

      那么由于整棵树度数为偶数的节点有奇数个,所以去掉以 为根的子树后(X的父节点度数会发生改变),剩下的节点中,度数为偶数的节点仍然为奇数个

      对于以 X 为根的子树,因为除了根节点 X 以外其他节点度数均为奇数,所以可以通过一个简单的 DFS 直接清除整棵以 X 为根节点的子树

      去掉 X 后继续往上回溯,找到下一个度数为偶数的节点,过程同上。

    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <cstdio>
    #include <queue>
    #include <vector>
    #include <set>
    
    using namespace std;
    
    const int M=2e5+44;
    
    vector<int> vec[M];
    int du[M],tag[M];
    int n;
    queue<int> que;
    int ans[M],lans;
    
    void dfs(int rt,int fa)
    {
    	int v,now,tmp;
    	for(int i=0;i<vec[rt].size();i++)
    		if(vec[rt][i]!=fa)
    			dfs(vec[rt][i],rt);
    	if((du[rt]&1)==0)
    	{
    		que.push(rt); du[fa]--;
    		while(!que.empty())
    		{
    			now=que.front(); que.pop();
    			ans[++lans]=now; tag[now]=1;
    			for(int i=0;i<vec[now].size();i++)
    			{
    				v=vec[now][i]; if(v==fa) continue; if(tag[v]) continue;
    				du[v]--; que.push(v);
    			}
    		}
    	}
    }
    
    int main()
    {
    	int tmp;
    	memset(du,0,sizeof(du));
    	scanf("%d",&n);
    	if((n&1)==0)
    		return puts("NO"),0;
    	for(int i=1;i<=n;i++)
    		vec[i].clear();
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&tmp); if(tmp==0) continue;
    		du[i]++; du[tmp]++;
    		vec[i].push_back(tmp); vec[tmp].push_back(i);
    	}
    	while(!que.empty()) que.pop();
    	dfs(1,-1);
    	if(lans!=n) return puts("??"),0;
    	puts("YES");
    	for(int i=1;i<=lans;i++)
    		printf("%d
    ",ans[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    Java 简单算法--打印乘法口诀(只使用一次循环)
    Java简单算法--求100以内素数
    ubuntu 16.04 chrome flash player 过期
    java 网络API访问 web 站点
    java scoket (UDP通信模型)简易聊天室
    leetcode1105 Filling Bookcase Shelves
    leetcode1140 Stone Game II
    leetcode1186 Maximum Subarray Sum with One Deletion
    leetcode31 Next Permutation
    leetcode834 Sum of Distances in Tree
  • 原文地址:https://www.cnblogs.com/FxxL/p/8882051.html
Copyright © 2011-2022 走看看