zoukankan      html  css  js  c++  java
  • 洛谷 P4408 [NOI2003] 逃学的小孩 题解

    Analysis

    题意虽然说先去谁家再去谁家,但是我们不需要管这个,因为AA、BB、CC三个点我们可以任意互相交换它们所代表的对象,所以题目要求的就是在一棵树上找到3个点AA、BB、CC令AB+BCAB+BC最大,同时要满足AC>ABAC>AB。

    由于这是一棵树,它满足非常可爱的性质,就是如果找一个点出去两条路径使它们的合最大,那么一条是直径时一定会存在一种最大的方案。

    所以我们可以使要找的两条路径其中一条是直径(设为ABAB),然后枚举剩下的点,找到一个到达直径端点最长的另一条路径,不过因为题目要满足一个AC>ABAC>AB,所以我们需要在每次枚举的时候(设为CC),选择ACAC和BCBC的较小的一条边作为另一条路径。可以看到,若是ACAC是小于BCBC的,则选择的路径是ACAC,实际走的路线是CACA+ABAB,满足题目要求的CA<CBCA<CB,而若是选择的是BCBC,实际路线是CBCB+BABA,也符合题意要求的CB<CACB<CA。

    至此,就可以写出代码了,跑2遍dfs找出直径,再对直径起点和终点跑出对每个点的路径长度,然后计算答案。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #define int long long
      6 #define maxn 200000+10
      7 using namespace std;
      8 inline int read() 
      9 {
     10     int x=0;
     11     bool f=1;
     12     char c=getchar();
     13     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
     14     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
     15     if(f) return x;
     16     return 0-x;
     17 }
     18 inline void write(int x)
     19 {
     20     if(x<0){putchar('-');x=-x;}
     21     if(x>9)write(x/10);
     22     putchar(x%10+'0');
     23 }
     24 int n,m,cnt,com,sta,ed,ans;
     25 int dis1[maxn],dis2[maxn],head[2*maxn];
     26 struct node
     27 {
     28     int to,val,nxt;
     29 }edge[2*maxn];
     30 inline void add(int x,int y,int z)
     31 {
     32     cnt++;
     33     edge[cnt].to=y;
     34     edge[cnt].val=z;
     35     edge[cnt].nxt=head[x];
     36     head[x]=cnt++;
     37 }
     38 inline void dfs1_tree_d(int x,int fa)
     39 {
     40     for(int i=head[x];i;i=edge[i].nxt)
     41     {
     42         int to=edge[i].to;
     43         if(to==fa) continue;
     44         dis1[to]=dis1[x]+edge[i].val;
     45         if(dis1[to]>com) 
     46         {
     47             com=dis1[to];
     48             sta=to;
     49         }
     50         dfs1_tree_d(to,x);
     51     }
     52 }
     53 inline void dfs2_tree_d(int x,int fa)
     54 {
     55     for(int i=head[x];i;i=edge[i].nxt)
     56     {
     57         int to=edge[i].to;
     58         if(to==fa) continue;
     59         dis2[to]=dis2[x]+edge[i].val;
     60         if(dis2[to]>com) 
     61         {
     62             com=dis2[to];
     63             ed=to;
     64         }
     65         dfs2_tree_d(to,x);
     66     }
     67 }
     68 inline void find1_long(int x,int fa)
     69 {
     70     for(int i=head[x];i;i=edge[i].nxt)
     71     {
     72         int to=edge[i].to;
     73         if(to==fa) continue;
     74         dis1[to]=dis1[x]+edge[i].val;
     75         find1_long(to,x);
     76     }
     77 }
     78 inline void find2_long(int x,int fa)
     79 {
     80     for(int i=head[x];i;i=edge[i].nxt)
     81     {
     82         int to=edge[i].to;
     83         if(to==fa) continue;
     84         dis2[to]=dis2[x]+edge[i].val;
     85         find2_long(to,x);
     86     }
     87 }
     88 signed main()
     89 {
     90 //    freopen("truant.in","r",stdin);
     91 //    freopen("truant.out","w",stdout);
     92     n=read();m=read();
     93     for(int i=1;i<=m;i++)
     94     {
     95         int x=read(),y=read(),z=read();
     96         add(x,y,z);
     97         add(y,x,z);
     98     }
     99     com=0;
    100     dfs1_tree_d(1,0);
    101     com=0;
    102     dfs2_tree_d(sta,0);
    103     ans=dis2[ed];
    104     memset(dis1,0,sizeof(dis1));
    105     memset(dis2,0,sizeof(dis2));
    106     find1_long(sta,0);
    107     find2_long(ed,0);
    108     com=0;
    109     for(int i=1;i<=n;i++)
    110     {
    111         int len=min(dis1[i],dis2[i]);
    112         if(len>com) com=len;
    113     }
    114     ans+=com;
    115     write(ans);
    116     return 0;
    117 }

    请各位大佬斧正(反正我不认识斧正是什么意思)

  • 相关阅读:
    mysql报错:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.
    MD5登陆密码的生成
    15. 3Sum、16. 3Sum Closest和18. 4Sum
    11. Container With Most Water
    8. String to Integer (atoi)
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    几种非线性激活函数介绍
    AI初探1
    AI初探
  • 原文地址:https://www.cnblogs.com/handsome-zyc/p/11628164.html
Copyright © 2011-2022 走看看