Saturday, December 15, 2018

[Gym] H. Capital City

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : H. Capital City
                    2015 ACM Arabella Collegiate Programming Contest
Source            : Gym
Category          : Graph Theory, Dynamic Programing
Algorithm         : Bridge Tree, DP on Tree
Verdict           : Accepted
#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
 
static const int maxn = 3e5 + 5;
 
struct node
{
    int v, e;
    ll w;
    node() {}
    node(int vv, int ee, ll ww) : v(vv), e(ee), w(ww) {}
};
 
vector <node> G[maxn];
bool isBridge[maxn], vis[maxn];
int timer, dis[maxn], low[maxn];
 
inline void findBridge(int u, int p = -1)
{
    vis[u] = 1;
    dis[u] = low[u] = timer++;
    for (auto &it : G[u])
    {
        int v = it.v;
        int e = it.e;
        if (v == p) continue;
        if (!vis[v])
        {
            findBridge(v, u);
            low[u] = min(low[u], low[v]);
            if (dis[u] < low[v]) isBridge[e] = 1;
        }
        else
        {
            low[u] = min(low[u], dis[v]);
        }
    }
}
 
int compo;
bool used[maxn];
int compo_num[maxn];
set <int> component[maxn];
vector <node> tree[maxn];
 
inline void bridgeTree(int src)
{
    used[src] = 1;
    int cur_compo = compo;
    compo_num[src] = cur_compo;
    component[cur_compo].insert(src);
    queue <int> PQ;
    PQ.push(src);
    while (!PQ.empty())
    {
        int u = PQ.front(); PQ.pop();
        for (auto &it : G[u])
        {
            int v = it.v;
            int e = it.e;
            ll w = it.w;
            if (used[v]) continue;
            if (isBridge[e])
            {
                compo++;
                tree[cur_compo].push_back(node(compo, e, w));
                tree[compo].push_back(node(cur_compo, e, w));
                bridgeTree(v);
            }
            else
            {
                PQ.push(v);
                used[v] = 1;
                compo_num[v] = cur_compo;
                component[cur_compo].insert(v);
            }
        }
    }
}
 
ll in[maxn], out[maxn];
 
inline void dfs(int u, int p)
{
    in[u] = 0;
    for (auto &it : tree[u])
    {
        int v = it.v;
        ll w = it.w;
        if (v == p) continue;
        dfs(v, u);
        in[u] = max(in[u], w + in[v]);
    }
}
 
inline void dfs2(int u, int p)
{
    ll mx1 = -1;
    ll mx2 = -1;
    for (auto &it : tree[u])
    {
        int v = it.v;
        ll w = it.w;
        if (v == p) continue;
        if (in[v]+w >= mx1)
        {
            mx2 = mx1;
            mx1 = w + in[v];
        }
        else if (in[v]+w > mx2)
        {
            mx2 = w + in[v];
        }
    }
    for (auto &it : tree[u])
    {
        int v = it.v;
        ll w = it.w;
        if (v == p) continue;
        ll use = mx1;
        if (in[v]+w == mx1) use = mx2;
        out[v] = max(w+out[u], w+use);
        dfs2(v, u);
    }
}
 
inline void init()
{
    timer = 1;
    compo = 1;
    for (int i = 0; i < maxn; i++)
    {
        dis[i] = 0;
        low[i] = 0;
        isBridge[i] = 0;
        vis[i] = 0;
        used[i] = 0;
        compo_num[i] = -1;
        G[i].clear();
        tree[i].clear();
        in[i] = 0;
        out[i] = 0;
        component[i].clear();
    }
}
 
int main()
{
    //freopen("in.txt", "r", stdin);
 
    int tc;
    scanf("%d", &tc);
    for (int tcase = 1; tcase <= tc; tcase++)
    {
        init();
        int tNode, tEdge;
        scanf("%d %d", &tNode, &tEdge);
        int root = 1;
        for (int e = 1; e <= tEdge; e++)
        {
            int u, v;
            ll w;
            scanf("%d %d %lld", &u, &v, &w);
            assert(u != v);
            root = max(root, max(u, v));
            G[u].push_back(node(v, e, w));
            G[v].push_back(node(u, e, w));
        }
        findBridge(root);
        bridgeTree(root);
        dfs(1, -1);
        dfs2(1, -1);
        ll maxCost = 1e15 + 5;
        int city = tNode + 1;
        for (int i = 1; i <= compo; i++)
        {
            ll cc = max(in[i], out[i]);
            if (cc < maxCost)
            {
                maxCost = cc;
                city = *component[i].begin();
            }
            else if (cc == maxCost)
            {
                city = min(city, *component[i].begin());
            }
        }
        printf("%d %lld\n", city, maxCost);
    }
}
 

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.