Gym100676 H. Capital City

 

感觉题目都已经快把正解给说出来了...
strongly connected的两个点的消耗为0,其实就是同一个边双连通分量里面的点消耗为0。
然后缩一下点,再树形DP一下就完了。
第一次写边双,但感觉挺简单的。

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 4e5 + 7;
int c[N];
bool bridge[N * 2];

struct E {
    int v, ne;
    ll c;
} e[N * 2], tree[N * 2];
int head[N], hd[N], cnt1, cnt2;
int dfn[N], low[N], id;
int color[N];

inline void add1(int u, int v, ll c) {
    e[++cnt1].v = v; e[cnt1].ne = head[u]; e[cnt1].c = c; head[u] = cnt1;
}

inline void add2(int u, int v, ll c) {
    tree[++cnt2].v = v; tree[cnt2].ne = hd[u]; tree[cnt2].c = c; hd[u] = cnt2;
}

void tarjan(int u, int edge) {
    dfn[u] = low[u] = ++id;
    for (int i = head[u]; i; i = e[i].ne) {
        int v = e[i].v;
        if (!dfn[v]) {
            tarjan(v, i);
            low[u] = min(low[u], low[v]);
            if (low[v] > low[u])
                bridge[i] = bridge[i ^ 1] = 1;
        } else if (i != (edge ^ 1))
            low[u] = min(low[u], dfn[v]);
    }
}

int dcc;

void dfs0(int u) {
    c[u] = dcc;
    color[dcc] = min(color[dcc], u);
    for (int i = head[u]; i; i = e[i].ne) {
        int v = e[i].v;
        if (c[v] || bridge[i]) continue;
        dfs0(v);
    }
}


ll dp[N][2];
int son[N][2];
void dfs(int u, int fa) {
    dp[u][0] = dp[u][1] = 0;
    son[u][0] = son[u][1] = 0;
    for (int i = hd[u]; i; i = tree[i].ne) {
        int v = tree[i].v;
        if (v == fa) continue;
        dfs(v, u);
        if (dp[v][0] + tree[i].c > dp[u][0]) {
            dp[u][1] = dp[u][0];
            son[u][1] = son[u][0];
            dp[u][0] = dp[v][0] + tree[i].c;
            son[u][0] = v;
        } else if (dp[v][0] + tree[i].c > dp[u][1]) {
            son[u][1] = v;
            dp[u][1] = dp[v][0] + tree[i].c;
        }
    }
}

void dfs2(int u, int fa, ll c) {
    if (fa) {
        if (son[fa][0] != u) {
            if (dp[fa][0] + c > dp[u][0]) {
                dp[u][1] = dp[u][0];
                son[u][1] = son[u][0];
                dp[u][0] = dp[fa][0] + c;
                son[u][0] = fa;
            } else if (dp[fa][0] + c > dp[u][1]) {
                son[u][1] = fa;
                dp[u][1] = dp[fa][0] + c;
            }
        } else {
            if (dp[fa][1] + c > dp[u][0]) {
                dp[u][1] = dp[u][0];
                son[u][1] = son[u][0];
                dp[u][0] = dp[fa][1] + c;
                son[u][0] = fa;
            } else if (dp[fa][1] + c > dp[u][1]) {
                son[u][1] = fa;
                dp[u][1] = dp[fa][1] + c;
            }
        }
    }
    for (int i = hd[u]; i; i = tree[i].ne) {
        int v = tree[i].v;
        if (v == fa) continue;
        dfs2(v, u, tree[i].c);
    }
}

int main() {
    freopen("in.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            head[i] = hd[i] = 0;
            c[i] = 0;
            low[i] = dfn[i] = 0;
            color[i] = n + 1;
        }
        memset(bridge, 0, sizeof(bridge));
        cnt1 = 1;
        for (int u, v, i = 1; i <= m; i++) {
            ll c;
            scanf("%d%d%lld", &u, &v, &c);
            add1(u, v, c);
            add1(v, u, c);
        }
        id = 0;
        for (int i = 1; i <= n; i++)
            if (!dfn[i])
                tarjan(i, 0);
        dcc = 0;
        for (int i = 1; i <= n; i++)
            if (!c[i]) {
                ++dcc;
                dfs0(i);
            }
        cnt2 = 1;
        for (int i = 2; i <= cnt1; i++) {
            int u = e[i ^ 1].v, v = e[i].v;
            if (c[u] == c[v]) continue;
            add2(c[u], c[v], e[i].c);
        }
        memset(dp, 0, sizeof(dp));
        dfs(1, 0);
        dfs2(1, 0, 0);
        int ans1 = 0; ll ans2 = 1e18;
        for (int i = 1; i <= dcc; i++) {
            if (dp[i][0] < ans2) ans2 = dp[i][0], ans1 = color[i];
            else if (dp[i][0] == ans2 && ans1 > color[i]) ans1 = color[i];
            //printf("%lld\n", dp[i][0]);
        }
        printf("%d %lld\n", ans1, ans2);
    }
    return 0;
}
View Code

 

posted @ 2019-10-14 21:51  Mrzdtz220  阅读(119)  评论(0编辑  收藏  举报