题的意思是说他本来给你一棵树然后你删掉或者加上一条边的花费都是1.问你最小花费数让它变成一个环。
出处是HDU 4714
思路其实挺简单的。
一直搜搜到底。然后回溯的时候的当前节点度数>2(如果是成环的话肯定就是2或者小于2)就把它和父节点之间的边砍掉。很强的一个地方也是一开始卡住的地方就是因为是回溯回来的。所以它下面的所有应该都是散的链。反正不成环。又因为对于一个点来说移动它的耗费一定是2.砍掉和再连上嘛。每次砍的时候*2就好了。至于父节点的标记数组为什么要-1.因为你在处理子节点的时候已经处理过了呀。相当于父节点可以少考虑一个节点了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int siz=1000000+10;
int book[siz];
vector<int>h[siz];
int ans=0;
void dfs(int son,int father){
for(int i=0;i<h[son].size();i++){
int newson=h[son][i];
if(newson==father) continue;
dfs(newson,son);
if(book[newson]>2){
book[son]--;
ans+=(book[newson]-2)*2;
}
}
}
int main(){
int T;
freopen("2.txt","r",stdin);
freopen("2.out","w",stdout);
scanf("%d",&T);
while(T--){
int N;
ans=0;
memset(book,0,sizeof(book));
scanf("%d",&N);
for(int i=1;i<=N;i++){
h[i].clear();
}
int a,b;
for(int i=0;i<N-1;i++){
scanf("%d%d",&a,&b);
book[b]++;
book[a]++;
h[a].push_back(b);
h[b].push_back(a);
}
int root=1;
for(int i=1;i<=N;i++){
if(book[i]==1){
root=i;
break;
}
}
dfs(root,0);
printf("%d\n",ans+1);
}
return 0;
}