APIO2010 巡逻

为获得更好的阅读体验请访问我的 Blog

Luogu

每添加一条边就会形成一个环,环上的边就都只用经过一次。所以 \(k=1\) 时候求下树的直径,令直径为 \(l_1\), \(2*(n-1)-l_1+1\) 就是答案了。

接下来我们来考虑 \(k=2\) 的时候。

肯定也是要连一条跟直径类似的路径的,但是可能会有边与之前 \(k=1\) 时连的重复。这时候本来这条边只需经过一次,现在变成了两次。所以,要将 \(k=1\) 时求出的直径上的路径的边权都变成 \(-1\) ,然后再求一遍直径。令这条直径为 \(l_2\) 答案就为 \(2*(n-1) - l_1 + 1 - l_2 + 1\) 化简得 \(2n-l_1-l_2\)

这里使用 树形Dp 来求树的直径。

#include <iostream>
#include <cstdio>
#include <cstring>

const int MaxN = 1e5 + 5;

int N, K, L1, L2, Edge, Ans, T1, T2;
int Dp[MaxN], FST[MaxN], W[MaxN], F[MaxN], Vis[MaxN];

struct Linker
{
    int to, nxt;
    Linker(){}
    Linker(int x, int y)
    {
        to = y;
        nxt = FST[x];
    }
} E[MaxN << 1];

inline int read()
{
    register int x = 0;
    register char ch = getchar();
    while(!isdigit(ch)) ch = getchar();
    while(isdigit(ch))
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x;
}

inline void AddEdge(int u, int v)
{
    E[++Edge] = Linker(u, v);
    FST[u] = Edge;
}

void DP(int x)
{
    Vis[x] = 1;
    for(int k = FST[x]; k; k = E[k].nxt)
    {
        int to = E[k].to, w = W[to] == 0 ? 1 : - 1;
        if(Vis[to]) continue; 
        DP(to);
        if(Dp[x] + Dp[to] + w > Ans)
        {
            Ans = Dp[x] + Dp[to] + w;
            T1 = F[x];
            T2 = to;
        }
        if(Dp[to] + w > Dp[x])
        {
            Dp[x] = Dp[to] + w;
            F[x] = to;
        }
    }
}

void paint(int x)
{
    if(!x) return;
    W[x] = 1;
    paint(F[x]);
}

int main()  
{
    N = read();
    K = read();
    for(int i = 1; i < N; ++i)
    {
        int u = read(), v = read();
        AddEdge(u, v);
        AddEdge(v, u);
    }
    DP(1);
    L1 = Ans;
    if(K == 1)
    {
        printf("%d\n", 2 * (N - 1) - L1 + 1);
        return 0;
    }
    else 
    {
        paint(T1);
        paint(T2);
        Ans = 0;
        memset(Dp, 0, sizeof(Dp));
        memset(F, 0, sizeof(F));
        memset(Vis, 0, sizeof(Vis));
        DP(1);
        L2 = Ans;
        printf("%d\n", 2 * N - L1 - L2);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zcdhj/p/9385008.html