• [ZJOI2008]骑士 基环树


    本人水平有限,题解不到为处,请多多谅解

    本蒟蒻谢谢大家观看

    题目传送门

    依据题意:我们可以知道这是一道环套树的题  (看了题解后)   QAQ

    先来介绍一下什么是基环树(环套树)。

    基环树:一棵树上只有一个环,比正常的树多一条边,也就是n个点n条边

    如图:

    普通树

     基环树(环套树):

    既然是基环树(又称环套树)的话,自然就先要找环

    找环如下:

     1 void dfs(int x,int fa){
     2     vis[x]=true;//x已经找过 
     3     for(int i=head[x];i!=-1;i=nxt[i]){
     4         int y=ver[i];
     5         if(y==fa)continue;
     6         if(!vis[y]){//若y没有找过,证明没有出现环 
     7             dfs(y,x);
     8         }
     9         else{//若y被找过,则一定有环 
    10             id=i;//左右节点连的边
    11             r1=x;//环的左节点 
    12             r2=y;//环的有节点 
    13         }
    14     }
    15 }

    我们又能联想到treedp当然也是看了题解)那到  没有上司的舞会  ,treedp是去还之后才能做的

    解释一下下面这句:

    id为环的边,因为建的时双向变,所以id^1就是另一条。例如id为x→y 然后id^1为y→x,因为异或为不进位加法,所以保证一奇一偶为连续的,一定为双向变。

    1 if(i==id||i==(id^1))continue;

    treedp如下:

     1 void treedp(int x,int fa){
     2     f[x][0]=0;//若不选当前节点,则值为0 
     3     f[x][1]=val[x];//若选当前节点,则取x的值 
     4     for(int i=head[x];i!=-1;i=nxt[i]){
     5         int y=ver[i];
     6         if(y==fa)continue;
     7         if(i==id||i==(id^1))continue;//当i为环的边时,要去环dp 
     8         treedp(y,x);
     9         f[x][0]+=max(f[y][0],f[y][1]);//当前点不取时,子节点可取可不取 
    10         f[x][1]+=f[y][0];//当前点不取时,子节点必须不取(依据题意) 
    11     }
    12 }

    之后我们要以环的两边节点各做一遍treedp来比较max

    并且环是不能取的

     1 for(int i=1;i<=n;i++){
     2         if(vis[i])continue;
     3         dfs(i,-1);
     4         treedp(r1,-1);
     5         sum=f[r1][0];
     6         memset(f,0,sizeof(f));
     7         treedp(r2,-1);
     8         sum=max(sum,f[r2][0]);
     9         ans+=sum;
    10     }

    至此,基本框架就介绍完了。

    下面上代码了

    code:

     1 #include<bits/stdc++.h>
     2 #pragma GCC optimize(3)
     3 const int N=1e6+10;
     4 using namespace std;
     5 int n,tot,id,r1,r2;
     6 int val[N],ver[N*2],head[N],nxt[N*2];
     7 long long f[N][2];
     8 bool vis[N];
     9 long long ans,sum;
    10 inline int read(){
    11     int x=0,f=1;char ch=getchar();
    12     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    13     while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    14     return x*f;
    15 }
    16 inline void write(int x)
    17 {
    18     if(x<0)x=-x,putchar('-');
    19     if(x>9)write(x/10);
    20     putchar(x%10+'0');
    21 }
    22 void add(int x,int y){
    23     ++tot;
    24     ver[tot]=y;
    25     nxt[tot]=head[x];
    26     head[x]=tot;
    27 }
    28 void treedp(int x,int fa){
    29     f[x][0]=0;
    30     f[x][1]=val[x];
    31     for(int i=head[x];i!=-1;i=nxt[i]){
    32         int y=ver[i];
    33         if(y==fa)continue;
    34         if(i==id||i==(id^1))continue;
    35         treedp(y,x);
    36         f[x][0]+=max(f[y][0],f[y][1]); 
    37         f[x][1]+=f[y][0];
    38     }
    39 }
    40 void dfs(int x,int fa){
    41     vis[x]=true;
    42     for(int i=head[x];i!=-1;i=nxt[i]){
    43         int y=ver[i];
    44         if(y==fa)continue;
    45         if(!vis[y]){
    46             dfs(y,x);
    47         }
    48         else{
    49             id=i;
    50             r1=x;
    51             r2=y;
    52         }
    53     }
    54 }
    55 int main()
    56 {
    57     memset(head,-1,sizeof(head));
    58     tot=1;
    59     memset(vis,0,sizeof(vis));
    60     n=read();
    61     for(int i=1,x,y;i<=n;i++){
    62         x=read(),y=read();
    63         val[i]=x;
    64         add(i,y);
    65         add(y,i);
    66     }
    67     for(int i=1;i<=n;i++){
    68         if(vis[i])continue;
    69         dfs(i,-1);
    70         treedp(r1,-1);
    71         sum=f[r1][0];
    72         memset(f,0,sizeof(f));
    73         treedp(r2,-1);
    74         sum=max(sum,f[r2][0]);
    75         ans+=sum;
    76     }
    77     printf("%lld
    ",ans);
    78     return 0;
    79 }
    80  
  • 相关阅读:
    WC命令
    dcoker machine
    linux命令
    Valgrind 检测程序内存使用
    golang flag
    面试之---二叉树的遍历
    FFMpeg 版本错误
    C++中namespace的使用
    QT之QStatusBar
    建立ftp服务器和客户端
  • 原文地址:https://www.cnblogs.com/nlyzl/p/11738211.html
Copyright © 2020-2023  润新知