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 ...
随机推荐
- 74th LeetCode Weekly Contest Valid Tic-Tac-Toe State
A Tic-Tac-Toe board is given as a string array board. Return True if and only if it is possible to r ...
- 大数据量高并发访问SQL优化方法
保证在实现功能的基础上,尽量减少对数据库的访问次数:通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担:能够分开的操作尽量分开处理,提高每次的响应速度:在数据窗口使用SQL时,尽量把 ...
- C# ThreadLocal
ThreadLocal的主要作用是让各个线程维持自己的变量. .NET 4.0在线程方面加入了很多东西,其中就包括ThreadLocal<T>类型,他的出现更大的简化了TLS的操作.Thr ...
- jquery——无缝滚动
无缝滚动: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- QT 简单的计算器例子
开发工具:vs2010.qt5.1 1使用vs新建工程,Base Class 选择QDialog
- QT源码解析笔记
1. QT如何绘制控件的 QT的绘制控件在QStyleSheetStyle::DrawControl里面,这里会调用默认的QSS来绘制效果 2. 在设置一次QSS以后,将会触发polish事件,里面将 ...
- IDEA/Eclipse安装 Alibaba Java Coding Guidelines 插件
为了让开发者更加方便.并且达到快速规范代码格式的目的并实行起来,阿里巴巴基于<阿里巴巴Java开发规约>手册内容,研发了一套自动化的IDE检测插件(IDEA.Eclipse).它就是Ali ...
- matlab 打不开excel文件
方法论 excel的后缀为.xls, matlab是无法识别的, 需要将其另存为.xlsx文件格式 打开excel, 点击save as, 选中保存的文件格式是.xlsx即可
- TemplateBinding与Binding区别,以及WPF自定义控件开发的遭遇
在上一次的文章WPF OnApplyTemplate 不执行 或者执行滞后的疑惑谈到怎么正确的开发自定义控件,我们控件的样式中,属性的绑定一般都是用TemplateBinding来完成,如下一个基本的 ...
- VMware 虚拟机安装及部署
Linux系统安装及网络配置 这篇文章介绍关于Linux系统的安装以及网络配置,关于虚拟机配置中网络的几个模式区别进行详细讲解.学习Linux对于后端开发人员来说是很有必要的,结合实际开发,Linux ...