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);
}
}