zoukankan      html  css  js  c++  java
  • bzoj1912: [Apio2010]patrol 巡逻

    曾系尴尬今天发现自己没写这题

    不建新边的话其实每条边都是走两次

    假如建一条新边相当于一条树上路径只用走一次

    那么当然选直径了

    但是建两条的话有可能树上路径有重叠部分,而每条边都需要经过,那么就会多减两次

    所以第一次选完以后把直径上的边变负容斥下

    恶心的是树上边权有负的时候是不能用两次dfs的方法找直径的。。。。。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    struct node
    {
        int x,y,d,next;
    }a[210000];int len,last[110000];
    void ins(int x,int y,int d)
    {
        len++;
        a[len].x=x;a[len].y=y;a[len].d=d;
        a[len].next=last[x];last[x]=len;
    }
    int d[2][110000],p[2][110000];
    void dfs(int x,int fr)
    {
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y!=fr)
            {
                dfs(y,x);
                if(d[0][y]+a[k].d>d[0][x])
                {
                    d[1][x]=d[0][x];
                    p[1][x]=p[0][x];
                    d[0][x]=d[0][y]+a[k].d;
                    p[0][x]=k;
                }
                else if(d[0][y]+a[k].d>d[1][x])
                {
                    d[1][x]=d[0][y]+a[k].d;
                    p[1][x]=k;
                }
            }
        }
    }
    
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int n,K,x,y;
        scanf("%d%d",&n,&K);
        len=1;memset(last,0,sizeof(last));
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            ins(x,y,1),ins(y,x,1);
        }
        int ans=(n-1)*2;
        for(int t=1;t<=K;t++)
        {
            memset(d,0,sizeof(d));
            memset(p,0,sizeof(p));
            dfs(1,0);
            int id=1;
            for(int i=2;i<=n;i++)
                if(d[0][i]+d[1][i]>d[0][id]+d[1][id])id=i;
            
            ans=ans-(d[0][id]+d[1][id])+1;
            for(int i=0;i<=1;i++)
                for(int k=p[i][id];k;k=p[0][a[k].y])
                    a[k].d=-a[k].d, a[k^1].d=-a[k^1].d;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Redis服务器配置
    Spark History Server配置使用
    CentOS7.3安装Nginx
    U盘安装CentOS7的最终解决方案
    iconfont_3种引用方式
    div+css 让一个小div在另一个大div里面 垂直居中
    JavaScript数组方法
    addEventListener()和removeEventListener()
    js获取网页高度
    Linux修改命令行样式
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9761079.html
Copyright © 2011-2022 走看看