zoukankan      html  css  js  c++  java
  • [IOI2013]Dreaming

    link

    一道非常类似的题目(link)

    试题大意

     给你一棵含有$n$个节点的有边权森林,问每次连边将会用$L$的代价,问你若此图通过加边成为树时的最小直径。$n leq 5 imes 10^5$

    试题分析

    我们可以发现若两棵树要是在合并连接的点一定与树的中心有关。树的中心指对于当$i$为根时,子树上权值和最大的最小。

    为什么,应为树的直径的情况只有单独一棵树,两棵树和在一起的,且那时要是合并就是的是树的中心。但其实$CF$那题应该求树的中心也行,因为那是边权都会为$1$.

    所以会发现其实应该如果说要把树建完以后会发现是一个菊花树,且根为权重最大的联通块的根。因为若是小的当根的话那么就会多算了一颗树,所以最多只需要算两颗即可。

    所以说我们每次处理好中心到叶子节点的最大距离是多少,然后就可以直接去计算答案了。

    并且为什么最多只要算到联通块个数$leq 3$呢,因为刚才说了这是一颗菊花图,所以我们最多有用的其实是两颗子树。

    IOI2013
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<climits>
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    const int N=500001;
    struct node{
        int u,v,w,nex;
    }x[N<<1];
    int cnt,head[N],n,m,l;
    void add(int u,int v,int w){
        x[cnt].u=u,x[cnt].v=v,x[cnt].w=w,x[cnt].nex=head[u],head[u]=cnt++;
    }
    int dp[N][3],dis[N],col,vis[N],son[N];
    /*0最长 1 次长*/
    void dfs1(int f,int fath){
        vis[f]=1;
        for(int i=head[f];i!=-1;i=x[i].nex){
            if(x[i].v==fath) continue;
            dfs1(x[i].v,f);
            if(dp[x[i].v][0]+x[i].w>=dp[f][0]){dp[f][1]=dp[f][0];dp[f][0]=dp[x[i].v][0]+x[i].w,son[f]=x[i].v;}
            else if(dp[x[i].v][0]+x[i].w>dp[f][1]){dp[f][1]=dp[x[i].v][0]+x[i].w;}
        }
        return;
    }
    int ans,k;
    void dfs2(int f,int fath,int Dis){
        if(Dis>dp[f][0]){
            dp[f][1]=dp[f][0];dp[f][0]=Dis;son[f]=fath;
        }
        else if(Dis>dp[f][1]){dp[f][1]=Dis;}
        ans=max(ans,dp[f][0]);k=min(k,dp[f][0]);
        for(int i=head[f];i!=-1;i=x[i].nex){
            if(x[i].v==fath) continue;
            if(son[f]==x[i].v) dfs2(x[i].v,f,dp[f][1]+x[i].w);
            else dfs2(x[i].v,f,dp[f][0]+x[i].w);
        }
    }
    int calc[N];
    signed main(){
        memset(head,-1,sizeof(head));
        n=read(),m=read(),l=read();
        for(int i=1;i<=m;i++){
            int u=read()+1,v=read()+1,w=read();
            add(u,v,w),add(v,u,w); 
        }
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                dfs1(i,0);
                k=INT_MAX;
                dfs2(i,0,0);
                calc[++col]=k;
            }
        }
        sort(calc+1,calc+col+1);
        if(col>=2) ans=max(ans,calc[col]+calc[col-1]+l);
        if(col>=3) ans=max(ans,calc[col-1]+calc[col-2]+2*l);
        printf("%d",ans);
    }

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<climits>
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    const int N=500001;
    struct node{
        int u,v,w,nex;
    }x[N<<1];
    int cnt,head[N],n,m,l;
    void add(int u,int v,int w){
        x[cnt].u=u,x[cnt].v=v,x[cnt].w=w,x[cnt].nex=head[u],head[u]=cnt++;
    }
    int dp[N][3],dis[N],col,vis[N],son[N];
    /*0最长 1 次长*/
    void dfs1(int f,int fath){
        vis[f]=1;
        for(int i=head[f];i!=-1;i=x[i].nex){
            if(x[i].v==fath) continue;
            dfs1(x[i].v,f);
            if(dp[x[i].v][0]+x[i].w>=dp[f][0]){dp[f][1]=dp[f][0];dp[f][0]=dp[x[i].v][0]+x[i].w,son[f]=x[i].v;}
            else if(dp[x[i].v][0]+x[i].w>dp[f][1]){dp[f][1]=dp[x[i].v][0]+x[i].w;}
        }
        return;
    }
    int ans,k,pos;
    struct Node{
        int pos,calc;
    }S[N<<1];
    void dfs2(int f,int fath,int Dis){
        if(Dis>dp[f][0]){
            dp[f][1]=dp[f][0];dp[f][0]=Dis;son[f]=fath;
        }
        else if(Dis>dp[f][1]){dp[f][1]=Dis;}
        ans=max(ans,dp[f][0]);k=min(k,dp[f][0]);
        if(dp[f][0]==k) pos=f;
        for(int i=head[f];i!=-1;i=x[i].nex){
            if(x[i].v==fath) continue;
            if(son[f]==x[i].v) dfs2(x[i].v,f,dp[f][1]+x[i].w);
            else dfs2(x[i].v,f,dp[f][0]+x[i].w);
        }
    }
    bool cmp(Node x1,Node x2){return x1.calc<x2.calc;}
    signed main(){
        memset(head,-1,sizeof(head));
        n=read(),m=read(),l=1;
        for(int i=1;i<=m;i++){
            int u=read(),v=read(),w=1;
            add(u,v,w),add(v,u,w); 
        }
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                dfs1(i,0);
                k=INT_MAX;
                dfs2(i,0,0);
                S[++col].calc=k;
                S[col].pos=pos;
            }
        }
        sort(S+1,S+col+1,cmp);
        if(col>=2) ans=max(ans,S[col].calc+S[col-1].calc+l);
        if(col>=3) ans=max(ans,S[col-1].calc+S[col-2].calc+2*l);
        printf("%d
    ",ans);
        for(int i=col-1;i>=1;i--) cout<<S[col].pos<<" "<<S[i].pos<<endl;
    }
    CF
  • 相关阅读:
    CF263E Rhombus
    AtCoder Grand Contest 034
    Docker C/S 架构逻辑图
    使用filledeat modules配置
    filebeat分别收集多个类型日志
    ELK部署收集日志
    ES界面
    Django下的post请求访问出现403错误
    Django配置(urls.py)
    Day-1 python
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/10143596.html
Copyright © 2011-2022 走看看