Codeforces 1029 E. Tree with Small Distances(树上dp)
题目直通车:http://codeforces.com/problemset/problem/1029/E
思路大意:在树上做dp,依次更新ar数组,ar[i]表示以i为根节点的子树对答案的最小贡献值,依次更新即可,具体细节见代码
/* 13 1 2 1 3 1 4 4 5 4 6 4 7 7 8 7 9 7 10 10 11 10 12 10 13 output:2 */ #include<iostream> #include<cstdio> #include<cmath> #include<queue> #include<vector> #include<string.h> #include<cstring> #include<algorithm> #include<set> #include<map> #include<fstream> #include<cstdlib> #include<ctime> #include<list> #include<climits> #include<bitset> using namespace std; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("input.in", "r", stdin);freopen("output.in", "w", stdout); #define left asfdasdasdfasdfsdfasfsdfasfdas1 #define tan asfdasdasdfasdfasfdfasfsdfasfdas typedef long long ll; typedef unsigned int un; const int desll[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; const ll mod=1e9; const int maxn=2e5+7; const int maxm=1e6+7; const double eps=1e-4; int m,n; int ar[maxn]; vector<int> ve[maxn]; int dis[maxn],ans,arTwo[maxn]; int sum,maxx; //arTwo[i]表示i节点与1相连时,以i为根的子树中需要与1相连的个数 //ar[i]表示以i为根节点的子树中需要与1相连的个数,即对答案的贡献值的最少值,dp更新ar即可 int func(int u,int pre,int num){ int mid=0; for(int i=0;i<ve[u].size();i++){ int v=ve[u][i]; if(v==pre)continue; if(num==2)mid += func(v,u,num-1); else mid+=ar[v]; } return min(mid, ar[u]); } void dfs2(int u,int pre){ for(int i=0;i<ve[u].size();i++){ int v=ve[u][i]; if(v==pre)continue; dfs2(v,u); } arTwo[u] = func(u,pre,2); ar[u]=arTwo[u]+1;//u节点与1相连的情况 int sumMid=0,maxMid=-n; for(int i=0;i<ve[u].size();i++){//u节点的一个子节点与1相连的情况 int v=ve[u][i]; if(v==pre)continue; sumMid += ar[v]; maxMid = max(maxMid, ar[v]-arTwo[v]-1); } if(sumMid==0)sumMid=1,maxMid=0;//特判子节点的情况 ar[u] = min(ar[u], sumMid-maxMid); } void funcDfs(int u,int pre,int num){ if(num==0){ int mid=0; for(int i=0;i<ve[u].size();i++){ int v=ve[u][i]; if(v==pre)continue; mid+=ar[v]; } ans += min(ar[u], mid); return ; } for(int i=0;i<ve[u].size();i++){ int v=ve[u][i]; if(v==pre)continue; funcDfs(v,u,num-1); } } int main() { scanf("%d",&n); fill(ar,ar+n+1,n); fill(arTwo,arTwo+n+1,n); for(int i=1;i<n;i++){ int a,b;scanf("%d%d",&a,&b); ve[a].push_back(b); ve[b].push_back(a); } ans=0; dfs2(1,-1); funcDfs(1,0,2); printf("%d\n",ans); return 0; }