zoukankan      html  css  js  c++  java
  • 【BZOJ】1912: [Apio2010]patrol 巡逻(树的直径)

    题目

    传送门:QWQ

    分析

    $ k=1 $ 时显然就是树的直径

    $ k=2 $ 时怎么做呢?

    做法是把一开始树的直径上的边的边权改成$ -1 $,那么当我们第二次用这些边做环时就抵消了一开始的贡献。

    所以答案就是边的数量*2 - 一开始树的直径 - 后来树的直径

     P.S. 第二次求树的直径时只能dp

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=210000;
    int n,dis[maxn], inq[maxn] ;
    struct Edge{ int u,v,dis; }; 
    vector<int> G[maxn]; vector<Edge> edges;
    queue<int> que;
    void addedge(int a,int b,int c){
        edges.push_back((Edge){a,b,c}); edges.push_back((Edge){b,a,c});
        int m=edges.size(); G[a].push_back(m-2); G[b].push_back(m-1);
    }
    int spfa(int s){
        memset(dis,-127,sizeof(dis));
        memset(inq,0,sizeof(inq));
        dis[s]=0;
        que.push(s);  inq[s]=1;
        while(!que.empty()){
            int u=que.front(); que.pop();
            for(int i=0;i<G[u].size();i++){
                int v=edges[G[u][i]].v; 
                if(!inq[v] && dis[v]<dis[u]+edges[G[u][i]].dis){
                    dis[v]=dis[u]+edges[G[u][i]].dis;
                    if(!inq[v]){que.push(v); inq[v]=1; }
                }
            }
        }
        int q=1,ans,maxnum=-10000000;
        for(int i=1;i<=n;i++) if(i!=s && dis[i]==dis[s]) q=0;
        for(int i=1;i<=n;i++){
            if(dis[i]>maxnum && (q||i!=s)){ maxnum=dis[i]; ans=i; }
        }
        return ans;
    }
    void dfs(int p,int fa){
        if(dis[p]==0) return;
        for(int i=0;i<G[p].size();i++){
            int v=edges[G[p][i]].v; 
            if(v!=fa && dis[v]==dis[p]-1){
                edges[G[p][i]].dis=-1; edges[G[p][i]^1].dis=-1; dfs(v,p);
            }
        }
    }
    int ansa=0;
    int dp(int x,int fa){
        int big1=0,big2=0;
        for(int i=0;i<G[x].size();i++){
            int v=edges[G[x][i]].v; if(v==fa) continue;
            int k=dp(v,x)+edges[G[x][i]].dis;
            if(big1<k){big2=big1; big1=k;}
            else if(big2<k){ big2=k; }
        }
        if(big1+big2 > ansa) ansa=big1+big2;
        return big1;
    }
    int main(){
        int a,b,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<n;i++){
            scanf("%d%d",&a,&b);
            addedge(a,b,1);
        }
        int p=spfa(1);
        int q=spfa(p); 
        int ans =2*n-1-dis[q];
        if(k==2){
             dfs(q,0); dp(1,0);
            ans-=ansa-1;
        } 
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    求原根
    koa2-router中间件来请求数据获取
    koa2 快速开始
    如何修改host
    bzoj 2480——扩展BSGS
    bzoj 4128: Matrix ——BSGS&&矩阵快速幂&&哈希
    Ubuntu 16.04LTS 安装和配置Bochs
    2019ICPC徐州网络赛 A.Who is better?——斐波那契博弈&&扩展中国剩余定理
    求十亿内所有质数的和
    MYSQL的随机查询的实现方法
  • 原文地址:https://www.cnblogs.com/noblex/p/9189447.html
Copyright © 2011-2022 走看看