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 ...
随机推荐
- python 数组学习
2 NumPy-快速处理数据 标准安装的Python中用列表(list)保存一组值,可以用来当作数组使用,不过由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针.这样为了保存一个简单的[1, ...
- 强联通分量之kosaraju算法
首先定义:强联通分量是有向图G=(V, E)的最大结点集合,满足该集合中的任意一对结点v和u,路径vu和uv同时存在. kosaraju算法用来寻找强联通分量.对于图G,它首先随便找个结点dfs,求出 ...
- 前后分离调用API跨域
前后分离调用API接口跨域问题 什么是跨域? 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的. 广义的跨域: 资源跳转:A链接.重定向.表单提交. 资源嵌入: <li ...
- 老男孩Day1作业(一):编写登录接口
需求:编写登陆接口1. 用户输入帐号密码进行登陆2. 用户信息保存在文件内3. 用户密码输入错误三次后锁定用户 1)编写思路 编写思路参考下面GitHub链接中的流程图 https://github. ...
- 关于unique去重
嗯.... unique这个东西也是一个冷门知识..... 但是在有时候它还是比较好用的东西... 下面就在详细代码中看unique是如何实际应用的....它主要是用于数组去重 #include< ...
- HTTP/TCP协议基础
HTTP协议 基本概念 HTTP协议(超文本传输协议 HyperText Transfer Protocol):是用于从WWW服务器传输超文本到本地浏览器的传送协议.它不仅保证计算机正确快速地传输超文 ...
- maven jetty 插件 允许修改 js
<!--允许修改js,css--> <servlet> <servlet-name>default</servlet-name> <init-pa ...
- tomcat内存配置
-Xms521M-Xmx1024M-XX:PermSize=64M -Xms256m -Xmx1024m -XX:MaxPermSize=256m
- .db文件打开方式
有时在工作中,数据库格式db后缀的格式,直接是打不开的,所以我这里使用了数据库管理工具,步骤如下 1. 在电脑安装 Navicat Premium,安装后在桌面生成图标,点击图标打开程序. 2.打开程 ...
- 018 4Sum 四个数的和
给定一个含有 n 个整数的数组 S,数列 S 中是否存在元素 a,b,c 和 d 使 a + b + c + d = target ?请在数组中找出所有满足各元素相加等于特定值的不重复组合.注意:解决 ...