D. Destruction of a Tree
题意:给你n个点,n-1条边连通整个图,每次删除度数为偶数的点,问是否能找出答案。
解法:偶数个点肯定不行。奇数个点,对于每个父亲儿子来说, 如果儿子的子树的大小为奇数, 那么肯定先删父亲, 反之先删儿子, 建立关系图, 跑一遍拓扑序就好啦。
#include <bits/stdc++.h>
using namespace std;
const int maxn=200005;
int n;
vector<int>v[maxn],v2[maxn];
int p[maxn];
int ds[maxn];
void gt(int st,int tt)
{
//cout<<st<<endl;
p[st]=1;
for(int i=0; i<v[st].size(); i++)
{
if(tt==v[st][i]) continue;
gt(v[st][i],st);
p[st]+=p[v[st][i]];
}
}
void dfs(int st,int tt)
{
for(int i=0; i<v[st].size(); i++)
{
if(v[st][i]==tt) continue;
int u=v[st][i];
cout<<u<<" "<<p[u]<<endl;
if(p[u]%2)
{
cout<<u<<endl;
v2[st].push_back(u);
ds[u]++;
}
else
{
v2[u].push_back(st);
ds[st]++;
}
dfs(u,st);
}
}
int main()
{
while(~scanf("%d",&n))
{
memset(p,0,sizeof(p));
memset(ds,0,sizeof(ds));
for(int i=1; i<=n; i++)
v[i].clear();
for(int i=1; i<=n; i++)
{
int vv;
scanf("%d",&vv);
if(vv!=0)
{
v[i].push_back(vv);
v[vv].push_back(i);
}
}
if(n%2==0)
{
printf("NO\n");
return 0;
}
gt(1,-1);
for(int i=1;i<=n;i++)
cout<<p[i]<<" ";
cout<<endl;
dfs(1,-1);
printf("YES\n");
queue<int>q;
for(int i=1; i<=n; i++)
{
if(!ds[i]) q.push(i);
}
while(!q.empty())
{
int p=q.front();
printf("%d\n",p);
q.pop();
for(int i=0; i<v[p].size(); i++)
{
int u=v[p][i];
ds[u]--;
if(!ds[u])
{
q.push(u);
}
}
}
}
return 0;
}