[WC2018]通道

题目:洛谷P4220、UOJ#347。

题目大意:给你三棵树,要你找到两个点,使其在三棵树上的最短路径和最大。

解题思路:正解是边分治,不会啊。于是本题可以随机化。

具体是,每次随机一个根,然后暴力找到一个点,该点在三棵树上到根距离和最大。然后以这个点为根继续做,迭代几遍。再重新随机一个根,以此类推(已经求过的根不需要再求)。

然后卡一下时间,在3000ms左右结束随机,输出答案即可。

注意当n小于8000时直接暴力,否则随机化可能会死循环。

于是n大的点,每个点都卡在3000ms左右。

C++ Code:

#include<bits/stdc++.h>
#define N 100005
#define TIME_LIMIT 2900
#define CLK (double)clock()/(double)CLOCKS_PER_SEC*1000.0
#define ll long long
int n;
bool ur[N];
ll ans=0;
inline int readint(){
    int c=getchar();
    for(;!isdigit(c);c=getchar());
    int d=0;
    for(;isdigit(c);c=getchar())
    d=(d<<3)+(d<<1)+(c^'0');
    return d;
}
inline ll debian(){
    int c=getchar();
    for(;!isdigit(c);c=getchar());
    ll d=0;
    for(;isdigit(c);c=getchar())
    d=(d<<3)+(d<<1)+(c^'0');
    return d;
}
struct Graph{
    int cnt,head[N];
    ll dis[N];
    struct edge{
        int to,nxt;
        ll dis;
    }e[N<<1];
    inline void addedge(int u,int v,ll w){
        e[++cnt]=(edge){v,head[u],w};
        head[u]=cnt;
        e[++cnt]=(edge){u,head[v],w};
        head[v]=cnt;
    }
    Graph():cnt(0){
        memset(head,0,sizeof head);
    }
    void dfs(int now,int pre){
        for(int i=head[now];i;i=e[i].nxt)
        if(e[i].to!=pre){
            dis[e[i].to]=dis[now]+e[i].dis;
            dfs(e[i].to,now);
        }
    }
}G[3];
void not_rand(){
    for(int i=1;i<=n;++i){
        G[0].dis[i]=G[1].dis[i]=G[2].dis[i]=0;
        G[0].dfs(i,0),G[1].dfs(i,0),G[2].dfs(i,0);
        for(int j=1;j<=n;++j){
            ll now=G[0].dis[j]+G[1].dis[j]+G[2].dis[j];
            if(now>ans)ans=now;
        }
    }
    printf("%lld\n",ans);
}
int main(){
    memset(ur,0,sizeof ur);
    srand(20170607);
    n=readint();
    for(int i=1;i<n;++i){
        int u=readint(),v=readint();
        ll w=debian();
        G[0].addedge(u,v,w);
    }
    for(int i=1;i<n;++i){
        int u=readint(),v=readint();
        ll w=debian();
        G[1].addedge(u,v,w);
    }
    for(int i=1;i<n;++i){
        int u=readint(),v=readint();
        ll w=debian();
        G[2].addedge(u,v,w);
    }
    double BEG=CLK;
    if(n<=8000){not_rand();return 0;}
    while(CLK-BEG<=TIME_LIMIT){
        int rt=(ll)rand()*rand()%n+1;
        while(ur[rt]&&CLK-BEG<=TIME_LIMIT)rt=(ll)rand()*rand()%n+1;
        for(int i=1;i<10;++i){
            if(ur[rt])break;
            ur[rt]=1;
            G[0].dis[rt]=G[1].dis[rt]=G[2].dis[rt]=0;
            G[0].dfs(rt,0),G[1].dfs(rt,0),G[2].dfs(rt,0);
            ll mx=0;
            for(int j=1;j<=n;++j){
                ll now=G[0].dis[j]+G[1].dis[j]+G[2].dis[j];
                if(now>ans)ans=now;
                if(!ur[j]&&now>mx){
                    mx=now,rt=j;
                }
            }
        }
    }
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2018-03-26 18:50  Mrsrz  阅读(488)  评论(0编辑  收藏  举报