P3629 [APIO2010]巡逻

用取反的方法来处理两个环相交的情况,,,
妙啊, 妙啊

#include <vector>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1e5 + 10;
inline int read(){
    char ch = getchar(); int x = 0;
    while(!isdigit(ch)) ch = getchar();
    while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
    return x;
}

struct edge
{
    int to, cost, rev;
};

int N, K;
vector<edge> g[MAXN];

int dis[MAXN]; bool vis[MAXN];
void dfs(int u, int dep) {
    if(vis[u]) return ;

    vis[u] = true; dis[u] = dep;
    for(int i = 0; i < (int) g[u].size(); i++) {
        edge &e = g[u][i];
        dfs(e.to, dep + e.cost);
    }
}

bool give_tag(int u, int tag, int fa) {
    if(u == tag) return true;
    for(int i = 0; i < (int) g[u].size(); i++) {
        edge &e = g[u][i];
        if(e.to == fa) continue;
        if(give_tag(e.to, tag, u)) {
            e.cost = g[e.to][e.rev].cost = -1;
            return true;
        }
    }
    return false;
}

int len = 0;
void dp(int u) {
    vis[u] = true;

    for(int i = 0; i < (int) g[u].size(); i++) {
        edge &e = g[u][i];
        if(vis[e.to]) continue;
        dp(e.to);
        len = max(len, dis[u] + dis[e.to] + e.cost);
        dis[u] = max(dis[u], dis[e.to] + e.cost);
    }
}

int main(){
    // freopen("p3629.in", "r", stdin);
    cin>>N>>K;
    for(int i = 1; i < N; i++) {
        int u = read(), v = read();
        g[u].push_back((edge){v, 1, g[v].size()}), 
        g[v].push_back((edge){u, 1, g[u].size() - 1});
    }
    dfs(1, 0);

    int ans = 0, st = 1, ed = 1;
    for(int i = 1; i <= N; i++) if(dis[i] > ans) 
        ans = dis[i], st = i;

    memset(dis, 0, sizeof(dis)), memset(vis, false, sizeof(vis));
    dfs(st, 0); ans = 0;
    for(int i = 1; i <= N; i++) if(dis[i] > ans) 
        ans = dis[i], ed = i;

    if(K == 1) return printf("%d\n", ((N - 1) << 1) - ans + 1), 0;

    give_tag(st, ed, st);
    memset(dis, 0, sizeof(dis)), memset(vis, false, sizeof(vis));
    dp(1);
    printf("%d\n", (N << 1) - ans - len);
    return 0;
}
posted @ 2018-10-17 16:52  俺是小程  阅读(97)  评论(0编辑  收藏  举报