Gym - 100676H Capital City(边强连通分量 + 树的直径)
H. Capital City
[ Color: Black ]
Bahosain has become the president of Byteland, he is doing his best to make people's lives
easier. Now, he is working on improving road networks between the cities.
If two cities are strongly connected, people can use BFS (Bahosain's Fast Service) to travel
between them in no time. Otherwise, they have to follow one of the shortest paths between
them, and of course, they will use BFS when they can!
Two cities are connected if there is a path between them, and they are strongly connected if
after removing any single road they will remain connected.
President Bahosain wants to minimize the maximum distance people have to travel from any city
to reach the capital city, can you help him in choosing the capital city?
Input
The first line of input contains one integer T, the number of test cases (1 ≤ T ≤ 64).
The first line of each test case contains two integers n, m (1 ≤ n ≤ 100,000) (0 ≤ m ≤ 200,000), the
number of cities and the number of roads, respectively.
Each of the following m lines contains three space-separated integers a, b, c (1 ≤ a, b ≤ n) (1 ≤ c ≤
100,000), meaning that there is a road of length c connecting the cities a and b.
Byteland cities are connected since Bahosain became the president.
Test cases are separated with a blank line.
Output
For each test case, print the number of the city and length of the maximum shortest path on a
single line. If there is more than one possible city, print the one with the minimum number.
Sample Input
1
7 7
1 2 5
1 7 5
3 2 5
1 3 5
3 4 3
6 4 1
4 5 3
Sample Output
1 6
题意:
在有个王国中,所有的城市都是间接或直接连通的,然后对于两个城市之间的路程,如果这两个城市是强连通的话,他们之间的路程可以看成0,否则的话就是路径的距离,强连通的话就是删除任何的一条路,这两个城市也是连通的,那么他们就是强连通的(Two cities are connected if there is a path between them, and they are strongly connected if after removing any single road they will remain connected.),现在这个王国要定首都,问首都定在哪个城市,能够让离首都最远的城市最近,输出首都的城市的编号和离首都最远的城市的距离,如果有多个的话城市编号最小。
思路:
题目说得很明显,肯定是要边双连通分量缩点,将所有的边双连通分量缩点之后就会形成一颗树,所以问题就转化成了在一颗树上找一个点、使树上离这个点的最远的距离最短,然后考虑树的直径,为什么呢,假设当前点是树的直径上面的点,那么没有任何点的距离到该点的距离大于该点到直径两段的最大距离要大;然后假设当前点不是直径上面的点,那么当前点连到直径上的节点要比当前点更优

代码:
/** @xigua */
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
#include<queue>
#include<set>
#include<string>
#include<map>
#include<climits>
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
const int INF = 1e8 + 5;
const ll inf = 1e15 + 5;
const db eps = 1e-9; struct Edge {
ll u, v, c;
} e[maxn<<2];
struct Ed {
ll v, c;
};
int n, m, low[maxn], pre[maxn], tim, ebcc_cnt, du[maxn];
ll k, len, dis[maxn][2];
vector<int> G[maxn];
vector<Ed> ed[maxn];
int isbri[maxn<<4];
bool vis[maxn]; void init() {
ebcc_cnt = tim = 0;
for (int i = 1; i <= n; i++) G[i].clear();
memset(isbri, 0, sizeof(isbri));
memset(pre, 0, sizeof(pre));
memset(du, 0, sizeof(du));
} void tarjan(int u, int fa) {
low[u] = pre[u] = ++tim;
for (int i = 0; i < G[u].size(); i++) {
int tmp = G[u][i];
int v = e[tmp].v;
if (!pre[v]) {
tarjan(v, u);
low[u] = min(low[u], low[v]);
if (low[v] > pre[u]) // 子节点的反向边大于当前节点
isbri[tmp] = isbri[tmp^1] = true; //标记为桥
}
else if (fa != v) // fa很重要 对于桥
low[u] = min(low[u], pre[v]);
}
} void dfs(int u) {
pre[u] = ebcc_cnt;
for (int i = 0; i < G[u].size(); i++) {
int tmp = G[u][i];
if (isbri[tmp]) continue;
int v = e[tmp].v;
if (pre[v]) continue;
dfs(v);
}
} void find_ebcc() {
tarjan(1, -1);
memset(pre, 0, sizeof(pre));
for (int i = 1; i <= n; i++) {
if (!pre[i]) {
ebcc_cnt++;
dfs(i);
}
}
} void BFS(int s, int ca) {
memset(vis, 0, sizeof(vis));
queue<Ed> q;
q.push((Ed){s, 0});
vis[s] = 1;
while (q.size()) {
Ed tmp = q.front(); q.pop();
dis[tmp.v][ca] = tmp.c;
for (int i = 0; i < ed[tmp.v].size(); i++) {
Ed xx = ed[tmp.v][i];
if (!vis[xx.v]) {
vis[xx.v] = 1;
q.push((Ed){xx.v, xx.c + tmp.c});
}
}
}
} void dfs_len(int x, int fa, ll dep) { //找直径
if (dep > len) {
k = x;
len = dep;
}
for (int i = 0; i < ed[x].size(); i++) {
Ed tmp = ed[x][i];
if (tmp.v == fa) continue;
dfs_len(tmp.v, x, dep + tmp.c);
}
} void solve() {
cin >> n >> m;
init();
for (int i = 1; i <= m; i++) {
int u, v, c; scanf("%d%d%d", &u, &v, &c);
e[i<<1|1].u = u, e[i<<1|1].v = v, e[i<<1|1].c = c;
e[i<<1].u = v, e[i<<1].v = u, e[i<<1].c = c;
G[u].push_back(i<<1|1);
G[v].push_back(i<<1);
}
find_ebcc();
int tot = m<<1|1;
for (int i = 1; i <= ebcc_cnt; i++) ed[i].clear();
for (int i = 1; i <= tot; i += 2) {
if (isbri[i]) {
int u = e[i].v, v = e[i].u;
ed[pre[u]].push_back((Ed){pre[v], e[i].c});
ed[pre[v]].push_back((Ed){pre[u], e[i].c});
}
}
len = -1;
dfs_len(1, -1, 0);
int st = k; len = -1;
dfs_len(st, -1, 0);
BFS(st, 0); //直径的两个端点
BFS(k, 1);
ll inx = n + 1, dd = inf;
for (int i = 1; i <= n; i++) {
int pr = pre[i];
if (dis[pr][0] + dis[pr][1] != len) continue; //判断是否是直径上的点
ll tmp = max(dis[pr][0], dis[pr][1]);
if (tmp < dd) {
inx = i;
dd = tmp;
}
}
cout << inx << ' ' << dd << endl;
} int main() {
//cin.sync_with_stdio(false);
//freopen("tt.txt", "r", stdin);
//freopen("hh.txt", "w", stdout);
int t = 1; cin >> t; while (t--) {
solve();
}
return 0;
}
/*
2
7 7
1 2 5
1 7 5
3 2 5
1 3 5
3 4 3
6 4 1
4 5 3
3 3
1 2 3
1 3 3
2 3 3
*/
Gym - 100676H Capital City(边强连通分量 + 树的直径)的更多相关文章
- CodeForcesGym 100676H Capital City
H. Capital City Time Limit: 3000ms Memory Limit: 262144KB This problem will be judged on CodeForcesG ...
- ACM Arabella Collegiate Programming Contest 2015 H. Capital City 边连通分量
题目链接:http://codeforces.com/gym/100676/attachments 题意: 有 n 个点,m 条边,图中,边强连通分量之间可以直达,即距离为 0 ,找一个点当做首都,其 ...
- codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点
J. Computer Network Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Des ...
- Gym - 100781A Adjoin the Networks (树的直径)
题意: n个点,m条边,m <= n <= 100000,边的长度都为1. 点从 0 ~ n-1 编号.开始时图是不连通的,并且没有环. 通过加入一些边后,可以使图连通.要求加入的边不能多 ...
- Gym - 100676H H. Capital City (边双连通分量缩点+树的直径)
https://vjudge.net/problem/Gym-100676H 题意: 给出一个n个城市,城市之间有距离为w的边,现在要选一个中心城市,使得该城市到其余城市的最大距离最短.如果有一些城市 ...
- codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径
题目链接: http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” ...
- hdoj 4612 Warm up【双连通分量求桥&&缩点建新图求树的直径】
Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Su ...
- HDU 4612 Warm up (边双连通分量+缩点+树的直径)
<题目链接> 题目大意:给出一个连通图,问你在这个连通图上加一条边,使该连通图的桥的数量最小,输出最少的桥的数量. 解题分析: 首先,通过Tarjan缩点,将该图缩成一颗树,树上的每个节点 ...
- HDU 4612——Warm up——————【边双连通分量、树的直径】
Warm up Time Limit:5000MS Memory Limit:65535KB 64bit IO Format:%I64d & %I64u Submit Stat ...
随机推荐
- static及静态方法
一.static 1.方法声明中用关键字static修饰的均为类方法或者静态方法,不用static修饰的方法称为实例方法: 2.实例方法可以调用该类中的实例方法或者类方法,类方法只能调用该类的类方法或 ...
- Java 异常处理基本规则,Java异常处理的基本规范
看了团队中原来代码中的异常处理,心碎了一地,稍微对照阿里巴巴的异常处理规范整理了一遍,准备分享一下,Java的异常处理规范&约束. 一.运行异常的扑捉 不要捕获 Java 类库中定义的继承自 ...
- redhat Enterprise Linux 6 VNC安装
redhat Enterprise Linux 6.2 beta VNC安装经验 VNC(Virtual Network Computing)是可操控远程的计算机的软件,任何人都可免费取得该软件,其 ...
- 40.QT-QPropertyAnimationdong和QParallelAnimationGroup动画实现
简述:QPropertyAnimation (动画类,用来向QObject对象添加动画) 该类的继承框图如下所示: 1.QAbstractAnimation(所有动画的抽象基类) 该抽象类为QProp ...
- [JLOI2012]树 倍增优化
题目描述 在这个问题中,给定一个值S和一棵树.在树的每个节点有一个正整数,问有多少条路径的节点总和达到S.路径中节点的深度必须是升序的.假设节点1是根节点,根的深度是0,它的儿子节点的深度为1.路径不 ...
- Django框架base.py源码
url.py文件 from django.conf.urls import url from django.contrib import admin from app_student import v ...
- LeetCode 136 Single Number 数组中除一个数外其他数都出现两次,找出只出现一次的数
Given an array of integers, every element appears twice except for one. Find that single one. class ...
- Git忽略提交规则
Git忽略提交规则 转自:https://www.cnblogs.com/kevingrace/p/5690241.html 在使用Git的过程中,我们喜欢有的文件比如日志,临时文件,编译的中间文件等 ...
- Java日志格式应该是占位符还是字符串拼接
背景 上次在群中,有个群友说自己把所有项目中,所有使用占位符打印日志的方式都修改成为了字符串拼接的方式,因为他曾经看了一篇文章,说字符串拼接的形式比占位符形式的性能更好,这个话题引起了大家的广泛讨 ...
- HttpClient4.6的使用
禁止转载,如需转载请联系本人 1)简介: HttpClient是apache的开源项目,弥补了Java自带的URLConnection功能不足,操作繁琐的缺点. 2)简单使用: a)get方式请求 / ...