hdu4714 Tree2cycle
原题链接:
题目大意:给一棵树节点数最多为1000000 ,把这棵树通过删边 和加边使这棵树变成一个环,其中删边和加边的的代价都为 1,输出最小代价。
题目分析:由于最终要形成一个环其拥有的的边一定为n,故可以只讨论要删除多少条边, 由于要形成环,删边后每个节点最多只能有两个节点,
如果 当前节点有多于2个子节点与其相连,其与父亲节点连接的边要删除。
喳喳代码:
#pragma comment(linker, "/STACK:167772160")//手动扩栈~~~~hdu 用c++交 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define N 1100000 using namespace std; vector<int> tree[N]; int n; int num; int dfs(int pos,int p)//如果当前节点与父亲节点的连线要删去返回1否则返回0 { int len=tree[pos].size(); if(len==1&&tree[pos][0]==p) return 1; int k=0;//记录当前节点的所有子节点返回的没有删除的与子节点连边的个数 int t; for(int i=0; i<len; i++) { t=tree[pos][i]; if(t==p)continue; k+=dfs(t,pos); } if(k>=2)//如果k>=2表示应该删除与父节点相连的边 { num+=k-2; if(pos!=1) num++; return 0; } return 1; } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1; i<=n; i++) tree[i].clear(); int a,b; for(int i=0; i<n-1; i++) { scanf("%d%d",&a,&b); tree[a].push_back(b); tree[b].push_back(a); } num=0;//表示要删除的边数 dfs(1,-1); int ans=2*num+1; printf("%d\n",ans); } return 0; }