zoukankan      html  css  js  c++  java
  • BZOJ

    题意:给定N点N边的无向连通图,现在让你在图中找一点作为餐厅,使得最远点距离这点最近。

    思路:为了保留整数,我们求最小直径,最后去除2。  直径来源于两部分:

            1,在外向树中; 那么就是树的直接,一棵树求直径直接跑一边DP就可以了。(或者两遍BFS吧,麻烦一点而已),假设最大值为ans1。

            2,可能通过了环。 一定有环上的边不在直接上,我们枚举这个断边。 那么现在就相当于一个X元环,环上的边有权值,X个点也各有权值,现在枚举每个断边,变成一条带枝桠的链,让你求ans2=min(最长链)。

    答案就是二者取max(ans1,ans2)。

    对于第二份部分,我们可以通过记录一个前缀和,一个后缀和,一个前缀答案,后缀答案,取得。

    而bzoj1791让你求基环树的直径,那就是所有位置取max,通过环的部分可以加倍成链用单调队列搞定。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=200010;
    int Laxt[maxn],Next[maxn],To[maxn],Len[maxn],cnt=1;
    int r[maxn],vis[maxn],tot;
    ll L[maxn],sum[maxn],ans,dp[maxn],p[maxn];
    void add(int u,int v,int w)
    {
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w;
    }
    bool dfs(int u,int f)
    {
        if(vis[u]==1)
          { vis[u]=2; r[++tot]=u;L[tot]=Len[f]; return true;} //开始出现环
        vis[u]=1;
        for(int i=Laxt[u];i;i=Next[i]){
            if(i==(f^1)) continue;
            if(dfs(To[i],i)) {
                if(vis[u]==2) return false; //环遍历完了
                else {vis[u]=2; r[++tot]=u; L[tot]=Len[f]; return true;}
            }
        }
        return false;
    }
    void treedp(int u,int f) //得到外向树的直径
    {
        for(int i=Laxt[u];i;i=Next[i]){
            if(i==(f^1)||vis[To[i]]==2) continue;
            treedp(To[i],i);
            ans=max(ans,dp[u]+Len[i]+dp[To[i]]);
            dp[u]=max(dp[u],dp[To[i]]+Len[i]);
        }
    }
    ll A[maxn],B[maxn],C[maxn],D[maxn];
    void solve()
    {
        ll P=0,Mx=0;
        rep(i,1,tot) p[i]=dp[r[i]];
        rep(i,1,tot){
             P+=L[i-1];
             A[i]=max(A[i-1],P+p[i]);
             C[i]=max(C[i-1],P+p[i]+Mx);
             Mx=max(Mx,p[i]-P);
        }
        P=0; Mx=0; ll res=C[tot];
        for(int i=tot;i>=1;i--){
            if(i==tot) P=0;
            else P+=L[i];
            B[i]=max(B[i+1],P+p[i]);
            D[i]=max(D[i+1],P+p[i]+Mx);
            Mx=max(Mx,p[i]-P);
        }
        rep(i,1,tot-1) {
            ll tmp=max(max(C[i],D[i+1]),A[i]+B[i+1]+L[tot]);
            res=min(res,tmp);
        }
        ans=max(ans,res);
    }
    int main()
    {
        int N,u,v,w;
        scanf("%d",&N);
        rep(i,1,N) {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w); add(v,u,w);
        }
        dfs(1,0);
        rep(i,1,tot) treedp(r[i],0);
        solve();
        printf("%lld",ans/2);
        if(ans&1) puts(".5");
        else puts(".0");
        return 0;
    }
  • 相关阅读:
    (转)C++ typename的起源与用法
    EOS智能合约深度解析
    cmake常用变量和命令解析
    (转)Linux下source命令详解
    eosio_install.sh执行过程
    java之collection总结
    Guava之RangeMap
    java file.listFiles()按文件名称、日期、大小排序
    Java下载文件的几种方式
    Java泛型Class<T>、T与Class<?>
  • 原文地址:https://www.cnblogs.com/hua-dong/p/11474399.html
Copyright © 2011-2022 走看看