随笔 - 58,  文章 - 0,  评论 - 4,  阅读 - 3296

一、题目描述:

  给你一棵 n 个点,n 条边的无向图,边带权,保证所有点都连通。

  求任意去掉一条边之后,在保持所有点依然都连通的情况下,直径的最小值。

  数据范围:3n2e5


 二、解题思路:

  首先我们找出环,我用的是拓扑排序,便于找出环上的点。

  考虑把这个图看成几棵分开的树,他们的根都在同一个环上,然后分类讨论:

  Situation 1:

    ,,

  Situation 2:

     ! ,

     cc , c1,c2,...,ccc

    prei  1  i ,

    sufi  i  n ,

    fi  ci , ci 

    , i, j,使 fi+fj+disi,j 

     ck  ck1 ,:

    Case 1: i,j, 1j<ik1

       fi+fj+dis+i,j=(prei+fi)(prejfj)=(fi+prei)+(fjprej)

       fi+prei,fiprei ,

    Case 2: i,j, ki<jcc

       Case 1  suf 

       fi+sufi,fisufi ,

    Case 3: i,j, 1ik1,kjcc

      li  max(fj+prej),j[1,i]

      ri  max(fj+sufj),j[r,cc]

       lk1+rk,

   至此,这个题终于分析完了。时间复杂度 O(n)


 三、完整代码:

复制代码
  1 #include<iostream>
  2 #define N 200010
  3 #define ll long long
  4 using namespace std;
  5 ll n,U,V,W,cc,ans1,ans2;
  6 ll du[N],p1[N],p2[N],v1[N],v2[N];
  7 ll c[N],f[N],q[N],a1[N],a2[N],val[N];
  8 ll l1[N],l2[N],fl[N],r1[N],r2[N],fr[N];
  9 struct EDGE{
 10     ll v,w,nxt;
 11 }edge[N*2];
 12 ll head[N],cnt;
 13 void add(ll u,ll v,ll w)
 14 {
 15     edge[++cnt].v=v;edge[cnt].w=w;
 16     edge[cnt].nxt=head[u];head[u]=cnt;
 17 }
 18 void top_sort()
 19 {
 20     ll l=1,r=0;
 21     for(ll i=1;i<=n;i++)
 22         if(du[i]==1)
 23             q[++r]=i,v1[i]=1;
 24     while(l<=r)
 25     {
 26         ll u=q[l];l++;
 27         for(ll i=head[u];i!=-1;i=edge[i].nxt)
 28         {
 29             ll to=edge[i].v;du[to]--;
 30             if(du[to]==1&&!v1[to])
 31                 v1[to]=1,q[++r]=to;
 32         }
 33     }
 34 }
 35 void dfs1(ll u,ll ff)
 36 {
 37     for(ll i=head[u];i!=-1;i=edge[i].nxt)
 38         if(edge[i].v!=ff&&!v1[edge[i].v])
 39         {
 40             v1[edge[i].v]=v2[edge[i].v]=1;
 41             c[++cc]=edge[i].v,val[cc]=edge[i].w;
 42             dfs1(edge[i].v,u);break;
 43         }
 44 }
 45 void dfs2(ll s,ll u,ll ff)
 46 {
 47     for(ll i=head[u];i!=-1;i=edge[i].nxt)
 48     {
 49         ll to=edge[i].v;
 50         if(v2[to])continue;
 51         v2[to]=1;dfs2(s,to,u);
 52         ll t=a1[to]+edge[i].w;
 53         if(t>a1[u])    a2[u]=a1[u],a1[u]=t;
 54         else    if(t>a2[u])        a2[u]=t;
 55     }
 56     f[s]=a1[u],ans1=max(ans1,a1[u]+a2[u]);
 57 }
 58 int main()
 59 {
 60     ios::sync_with_stdio(false);
 61     cin.tie(0);cout.tie(0);
 62     cin>>n;
 63     for(ll i=1;i<=n;i++)
 64         head[i]=-1;
 65     for(ll i=1;i<=n;i++)
 66     {
 67         cin>>U>>V>>W;
 68         add(U,V,W),du[U]++;
 69         add(V,U,W),du[V]++;
 70     }
 71     top_sort();
 72     for(ll i=1;i<=n;i++)
 73         if(!v1[i])
 74         {
 75             dfs1(i,0);
 76             break;
 77         }
 78     for(ll i=1;i<=cc;i++)
 79         dfs2(i,c[i],0);
 80     for(ll i=1;i<=cc;i++)
 81         p1[i]=p1[i-1]+val[i];
 82     for(ll i=cc;i>=1;i--)
 83         p2[i-1]=p2[i]+val[i];
 84     l1[0]=r1[cc+1]=-1e18,ans2=1e18;
 85     for(ll i=1;i<=cc;i++)
 86     {
 87         l1[i]=max(l1[i-1],f[i]-p1[i]);
 88         l2[i]=max(l2[i-1],f[i]+p1[i]);
 89         fl[i]=max(fl[i-1],f[i]+p1[i]+l1[i-1]);
 90     }
 91     for(ll i=cc;i>=1;i--)
 92     {
 93         r1[i]=max(r1[i+1],f[i]-p2[i]);
 94         r2[i]=max(r2[i+1],f[i]+p2[i]);
 95         fr[i]=max(fr[i+1],f[i]+p2[i]+r1[i+1]);
 96     }
 97     for(ll i=1;i<=cc;i++)
 98     {
 99         ll t1=l2[i-1]+r2[i];
100         ll t2=fl[i-1],t3=fr[i];
101         ans2=min(ans2,max(t1,max(t2,t3)));
102     }
103     cout<<max(ans1,ans2)<<'\n';
104     return 0;
105 }
复制代码

四、写题心得:

  这个题想了一整天,不过确实是一道好题。加油!拜拜!

posted on   trh0630  阅读(92)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示