题意:
给你一棵树,从树中取出一部分满足:是一条链+一些直接连在这条链上的节点
求节点数最多的合法取出部分。
题解:
其实这题还是不难?
观察到对于任意一条链,
只有两种情况: 一条路走到底 or 以某个点为中转
f[x]表示从x往下走,一路走到底的包括x的最优解,
f[x]包括x也包括father[x](将会加入它的贡献)
观察到以某个点为中转的情况:
倘若某条链以一个点为中转,那么这条链将无法向上产生贡献,
若没有,则变为第一种情况,且一定可以向上产生贡献, 以点x为中转的所有链都可以通过各个儿子的搭配得到
因此f[x]可以直接从f[son]中选取最优的来得到,
然后用f[x]来更新ans,
再选取儿子中的前2大,搭配起来加上x组成链,更新ans
所以dfs一遍然后输出ans即可,复杂度O(n);
细节还是挺多的,要注意。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define AC 350000 5 #define ACway 700000 6 #define getchar() *o++ 7 char READ[10001000],*o=READ; 8 int n,m,ans; 9 int in[AC],f[AC]; 10 int date[ACway],Head[AC],Next[ACway],tot; 11 /*观察到对于任意一条链,只有两种情况: 12 一条路走到底 :以某个点为中转 13 f[i]表示从i往下走,一条路走到底的最优解(不包括i)(非最长链) 14 但这样并不方便。。。。因为要分的情况太多, 15 所以f[x]表示从x往下走,一路走到底的包括x的最优解, 16 f[x]包括x也包括father[x] 17 观察到以某个点为中转的情况: 18 倘若某条链以一个点为中转,那么这条链将无法向上产生贡献, 19 若没有,则变为第一种情况。且一定可以向上产生贡献, 20 以点x为中转的所有链都可以通过各个儿子的搭配得到,*/ 21 22 inline int read() 23 { 24 int x=0;char c=getchar(); 25 while(c > ‘9‘ || c < ‘0‘) c=getchar(); 26 while(c >= ‘0‘ && c <= ‘9‘) x=x*10+c-‘0‘,c=getchar(); 27 return x; 28 } 29 30 inline void upmax(int &a,int b) 31 { 32 if(b > a) a=b; 33 } 34 35 inline void add(int f,int w) 36 { 37 date[++tot]=w,Next[tot]=Head[f],Head[f]=tot; 38 date[++tot]=f,Next[tot]=Head[w],Head[w]=tot; 39 ++in[f],++in[w]; 40 } 41 42 void pre() 43 { 44 int a,b; 45 n=read(),m=read(); 46 for(R i=1;i<=m;i++) 47 { 48 a=read(),b=read(); 49 add(a,b); 50 } 51 } 52 53 void dfs(int x,int fa) 54 { 55 int now,maxn=0,maxn2=0; 56 f[x]=1 + in[x];//因为包括了自己,所以至少也是1 + in[x]了 57 for(R i=Head[x] ; i ;i=Next[i]) 58 { 59 now=date[i]; 60 if(now == fa) continue; 61 dfs(now,x); 62 upmax(f[x],f[now] + in[x] - 1);//因为既要加自己,又要减儿子,抵消了,所以只用加in就可以了 63 if(f[now] > maxn)//但是由于f[now]会包括x,所以也要减掉,,, 64 { 65 maxn2=maxn; 66 maxn=f[now]; 67 } 68 else upmax(maxn2,f[now]); 69 } 70 upmax(ans,f[x]); 71 upmax(ans,maxn + maxn2 + in[x] - 3);//同上,只不过多减一个儿子 72 }//因为也会包括x,所以会重复2次 73 74 void work() 75 { 76 dfs(1,0);//随便选个点做根节点吧 77 printf("%d\n",ans); 78 // for(R i=1;i<=n;i++) printf("%d %d\n",i,f[i]); 79 } 80 81 int main() 82 { 83 // freopen("in.in","r",stdin); 84 fread(READ,1,10000000,stdin); 85 pre(); 86 work(); 87 // fclose(stdin); 88 return 0; 89 }
原文地址:https://www.cnblogs.com/ww3113306/p/9097545.html
时间: 2024-10-29 07:33:07