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 ...
随机推荐
- ARC085F(动态规划,线段树)
#include<bits/stdc++.h>using namespace std;const int maxn = 0x3f3f3f3f;int mn[801000];int cost ...
- 面向对象OO第三单元总结
第三单元OO总结博客 1 梳理JML语言的理论基础.应用工具链情况 由于篇幅原因,这里只梳理几个在本单元常用的 注释结构 行注释://@annotation 块注释:/* @ annotation @ ...
- IDEA开发Spark的漫漫摸索(一)
系统:Win10 01 安装IDEA IDEA版本:IntelliJ IDEA 2017.2.1 64位 使用的学生授权下载的ultimate版本,此处不赘叙安装过程. 02安装编译环境 Spark可 ...
- MySQL不同数据库之间表的简单同步
MySQL不同数据库之间表的简单同步,实用轻量级数据如下案列展示:例如我现在主库上面有users .tenants两张表需要同步到备库上面主库1.确认主库数据条数 select count(*) fr ...
- python右键Edit with IDLE
在windows下试用python,Py文件的右键菜单有个Edit with IDLE,虽然这个ide不是那么功能强大,但是胜在方便.对于脚本语言的一般使用来说是足够了.但是有时候,这个菜单就消失了, ...
- 忘记mysql数据库密码时进行修改方法
长时间没有使用数据库了,或者把密码改完之后就忘了数据库密码,不能正常进入数据库,也无法修改密码,有一个简单的常用修改密码方式: 1.首先找到和打开mysql.exe和mysqld.exe所在的文件夹( ...
- web 中防止sql注入
public class SqlInject:Page { //检测到注入后的处理方式: 0:仅警告:1:警告+记录:2:警告+自定义错误页面:3:警告+记录+自定义错误页面 ; private co ...
- Unity 关于激活
- SpringBoot | 第三章:springboot配置详解
基于springboot的约定优于配置的原则,在多数情况下,启动一个应用时,基本上无需做太多的配置,应用就能正常启动.但在大部分开发环境下,添加额外配置是无所避免的,比如自定义应用端口号(比较在机器比 ...
- SQL Server收缩数据库
USE[master]GOALTER DATABASE CCPG_SFY SET RECOVERY SIMPLE WITH NO_WAITGOALTER DATABASE CCPG_SFY SET R ...