边双连通缩点+树dp 2015 ACM Arabella Collegiate Programming Contest的Gym - 100676H
http://codeforces.com/gym/100676/attachments
题目大意:
有n个城市,有m条路,每条路都有边长,如果某几个城市的路能组成一个环,那么在环中的这些城市就有传送门,能够瞬间抵达对方的城市(即距离为0),否则,就要走这条路,并且经过的路程为这条路的长度。
问,找一个城市作为这些城市的首都
要求:除了首都城市外,其他城市到首都的最大距离最短。
思路:
边双连通缩点以后就是一棵树,找树上的直径,首都一定是直径上的点。(orz,自己明明注意到了一定是直径上面的点,在之前的好多次的wa中却忘了是要找直径上的点了)
//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
/*
思路:
双连通缩点,然后随便找一个点树dp,
树dp,距离最短的肯定就是直径上的某一个点
*/
const int maxn = 1e5 + ;
const int maxm = 2e5 + ;
const LL inf = 1e17;
vector<pair<int, LL> > G[maxn];
int n, m;
/*****************/
int dfstime, bcccnt;
bool iscut[maxn];
int bccnu[maxn], pre[maxn];
stack<int> s;
vector<int> bcc[maxn]; int dfs(int u, int fa){
int lowu = pre[u] = ++dfstime;
int len = G[u].size();
int child = ;
s.push(u);
for (int i = ; i < len; i++){
int v = G[u][i].fi;
if (pre[v] == -){
child++;
int lowv = dfs(v, u);
lowu = min(lowv, lowu);
if (lowv > pre[u]){
iscut[u] = true;
}
}
else if (pre[v] < pre[u] && v != fa){
lowu = min(lowu, pre[v]);
}
}
if (lowu == pre[u]){
bcccnt++;
while (true){///边双连通分量是不存在重点的
int v = s.top(); s.pop();
bccnu[v] = bcccnt;
bcc[bcccnt].pb(v);
if (v == u) break;
}
}
if (fa == - && child == ) iscut[u] = false;
return lowu;
} void get_connect(){
dfstime = bcccnt = ;
memset(iscut, false, sizeof(iscut));
memset(bccnu, , sizeof(bccnu));
memset(pre, -, sizeof(pre));
dfs(, -);
} vector<pair<int, LL> > new_edge[maxn];
void rebuild(){
///O(n + m)
for (int i = ; i <= bcccnt; i++){
for (int j = ; j < bcc[i].size(); j++){
int u = bcc[i][j];
for (int k = ; k < G[u].size(); k++){
int v = G[u][k].fi;
LL val = G[u][k].se;
if (bccnu[u] != bccnu[v]){
new_edge[bccnu[u]].push_back(mk(bccnu[v], val));
}
}
}
}
/* printf("bcccnt = %d\n", bcccnt); cout << "new_edge.output" << endl;
for (int i = 1; i <= bcccnt; i++){
for (int j = 0; j < new_edge[i].size(); j++){
printf("u = %d v = %d val = %d\n", i, new_edge[i][j].fi, new_edge[i][j].se);
}
cout << endl;
}
*/
} int p; LL maxval;
LL can[maxn];
void dfs1(int u, int fa, LL sum){
if (sum > maxval){
maxval = sum, p = u;
}
for (int i = ; i < new_edge[u].size(); i++){
int v = new_edge[u][i].fi;
LL tmp = new_edge[u][i].se;
if (v == fa) continue;
dfs1(v, u, sum + tmp);
}
} LL d1[maxn], d2[maxn];
///d1从最底下到目前节点的距离
///d2表示从根到目前节点的距离
void dfs2(int u, int fa, LL sum){
d2[u] = sum;
for (int i = ; i < new_edge[u].size(); i++){
int v = new_edge[u][i].fi;
LL val = new_edge[u][i].se;
if (v == fa) continue;
dfs2(v, u, sum + val);
d1[u] = max(d1[u], d1[v] + val);
}
} LL mini;
vector<int> ansp;
void dfs3(int u, int fa){
for (int i = ; i < new_edge[u].size(); i++){
int v = new_edge[u][i].fi;
LL val = new_edge[u][i].se;
if (v == fa) continue;
if (d1[u] - val == d1[v]){
dfs3(v, u);
LL tmp = max(d1[u], d2[u]);
if (mini > tmp){
ansp.clear(); mini = tmp; ansp.pb(u);
}
else if (mini == tmp){
ansp.pb(u);
}
}
}
} int main(){
int t; cin >> t;
while (t--){
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++){
G[i].clear(); bcc[i].clear();
new_edge[i].clear();
}
for (int i = ; i <= m; i++){
int u, v; LL val; scanf("%d%d%lld", &u, &v, &val);
G[u].pb(mk(v, val)); G[v].pb(mk(u, val));
}
get_connect();
rebuild();
p = , maxval = ;
dfs1(, -, ); memset(d1, , sizeof(d1));
memset(d2, , sizeof(d2));
ansp.clear();
dfs2(p, -, 0LL); mini = inf;
dfs3(p, -); int ans = n + ;
for (int i = ; i < ansp.size(); i++){
int u = ansp[i];
for (int j = ; j < bcc[u].size(); j++){
ans = min(ans, bcc[u][j]);
}
}
if (ans == n + ) {ans = , mini = ;}
printf("%d %lld\n", ans, mini);
}
return ;
}
边双连通缩点+树dp 2015 ACM Arabella Collegiate Programming Contest的Gym - 100676H的更多相关文章
- Codeforces Gym 2015 ACM Arabella Collegiate Programming Contest(二月十日训练赛)
A(By talker): 题意分析:以a(int) op b(int)形式给出两个整数和操作符, 求两个整数是否存在操作符所给定的关系 ,有则输出true,无则输出false: 思路:由于无时间复杂 ...
- 2015 ACM Arabella Collegiate Programming Contest
题目链接:https://vjudge.net/contest/154238#overview. ABCDE都是水题. F题,一开始分类讨论,结果似乎写挫了,WA了一发.果断换并查集上,A了. G题, ...
- gym100676 [小熊骑士限定]2015 ACM Arabella Collegiate Programming Contest
Kuma Rider久违的第二场训练,这场很水,又在vj的榜单上看到第一场的大哥了,2小时ak,大哥牛啤! A.水 #include<cstdio> #include<iostrea ...
- 18春季训练01-3/11 2015 ACM Amman Collegiate Programming Contest
Solved A Gym 100712A Who Is The Winner Solved B Gym 100712B Rock-Paper-Scissors Solved C Gym 100712C ...
- ACM Arabella Collegiate Programming Contest 2015 H. Capital City 边连通分量
题目链接:http://codeforces.com/gym/100676/attachments 题意: 有 n 个点,m 条边,图中,边强连通分量之间可以直达,即距离为 0 ,找一个点当做首都,其 ...
- 2015 ACM Amman Collegiate Programming Contest 题解
[题目链接] A - Who Is The Winner 模拟. #include <bits/stdc++.h> using namespace std; int T; int n; s ...
- 2015 ACM Syrian Collegiate Programming Contest
A. My Friend of Misery 计算出答案的上下界即可. 时间复杂度$O(n)$. #include<bits/stdc++.h> using namespace std; ...
- ACM Arabella Collegiate Programming Contest 2015 F. Palindrome 并查集
题目链接:http://codeforces.com/gym/100676/attachments 题意: 给一个字符串,有一些约束条件,两个位置要相同,有一些是问号,求最后有多少种方案回文? 分析: ...
- ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. Poor Ramzi -dp+记忆化搜索
ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. ...
随机推荐
- 团队backlog和燃尽图
首先我们的团队的任务是做一款一对一交流的软件,我们团队的backlog如下: 用电脑搭建一个服务器一对一平台 实现数据库和Android的链接 编写登陆,注册页面,和登陆成功界面,和登陆失败页面 实现 ...
- Traffic Steering for Service Function Chaining
Introduction 目前通过vlan标签来把流量引向对应的sfc 以前的sfc静态(SFs相邻组成SFC),有了sdn之后具有动态性.(SFs不需要彼此相邻.将流量动态地导向所需的SFs.) 流 ...
- lintcode-384-最长无重复字符的子串
384-最长无重复字符的子串 给定一个字符串,请找出其中无重复字符的最长子字符串. 样例 例如,在"abcabcbb"中,其无重复字符的最长子字符串是"abc" ...
- PAT 甲级 1020 Tree Traversals
https://pintia.cn/problem-sets/994805342720868352/problems/994805485033603072 Suppose that all the k ...
- Java MD5加密类
/************************************************* md5 类实现了RSA Data Security, Inc.在提交给IETF 的RFC1321中 ...
- json_decode遇到的编码问题
初入csdn,就最近遇到的简单问题做一个功能解释; json_encode和json_decode只针对utf8字符有效,如果遇到其他编码比如gbk,需要进行转码然后解析: header(" ...
- 查看apk包名和Activity名
今天遇到一个bug,比较有意思. 情景: 测试一个钻石提现功能,条件是账户里必须有价值等于或者超过50美元的钻石,才允许提现,否则无法进行下一步. 测试步骤: 提现页面输入一个小于50美元的提现金额, ...
- javascript+html5+css3下拉刷新 数据效果
文章摘自:suchso.com/projecteactual/javascript-html5-css3-taobao-xiala-data.html segmentfault.com/a/11900 ...
- 循环 与 next()
- hdfs源码分析第一弹
1. hdfs定义 HDFS is the primary distributed storage used by Hadoop applications. A HDFS cluster primar ...