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 ...
随机推荐
- jzoj3208. 【JSOI2013】编程作业(kmp)
题面 Description Will相信,很多同学都有过这样的经历:大牛已经写好了编程作业,而作为菜鸟的自己不会写怎么办呢?拿大牛的代码抄一下嘛!但是提交一模一样的作业是不是不太好?于是就改一改变量 ...
- 我的省选 Day -5
Day -5 时间载着我们,一天又一天,呼啸而过. 已经记不清今天是Day 负几了,总之还有不到一个星期就要去参加选拔赛了. 写一下今晚做NOI2009的心路历程. T1题意有点绕,但很快看出是个二分 ...
- 2018年12月25&26日
小结:昨天因为整理课件,调代码耗费了大量时间,所以没来得及整理作业,这两天主要做的题目是关于树链剖分和线段树的,难度大约都是省选难度,毕竟只要涉及到树链剖分难度就肯定不低. 一. 完成的题目: 洛谷P ...
- mariadb yum安装
安装 yum install mariadb mariadb-server -y 启动 systemctl start mariadb systemctl enable mariadb 安全安装 # ...
- EcmaScript学习
1.eval: ts: declare function eval(x: string): any; js: /** @param {*} x @return {Object} */ eval = f ...
- props简单小栗子
props简单小栗子 可以直接copy查看结果 <!DOCTYPE html> <html lang="en"> <head> <meta ...
- Chinese Zodiac (水题)
The Chinese Zodiac, known as Sheng Xiao, is based on a twelve-year cycle, each year in the cycle rel ...
- KMP 串的模式匹配 (25 分)
给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出.如果找不到,则输出“Not ...
- 转 oracle数据仓库部署注意事项(OLAP)
https://blog.csdn.net/laven54/article/details/9840365 最近数据库升级到11G之后,出现一些问题,慢慢的开始发现一些需要总结的东西,每次心里都在想: ...
- Java面向对象_常用类库api——二分查找算法
概念:又称为折半查找,优点是比较次数少,查找速度快,平均性能好:缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表. 例: public class Bi ...