https://vjudge.net/problem/Gym-100676H

题意:

给出一个n个城市,城市之间有距离为w的边,现在要选一个中心城市,使得该城市到其余城市的最大距离最短。如果有一些城市是强连通的,那么他们可以使用传送门瞬间到达。

思路:
因为强连通时可以瞬移,因为是无向图,所以计算边双连通分量然后重新建图,这样,也就不存在环了。

接下来,计算一下树的直径,因为中心城市肯定选在树的直径上,这样才有可能使最大的边最短。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
using namespace std; const int maxn=1e5+;
const long long INF =1e15+;
typedef pair<long long,long long> pll; struct Edge
{
long long u,v,c;
}edge[maxn<<]; int n,m;
int pre[maxn],isbridge[maxn<<],bcc_cnt,dfs_clock;
long long d[maxn][];
vector<int> G[maxn];
vector<pll> tree[maxn]; int tarjan(int u,int fa)
{
int lowu=pre[u]=++dfs_clock;
for(int i=;i<G[u].size();i++)
{
int temp=G[u][i];
int v=edge[temp].v;
if(!pre[v])
{
int lowv=tarjan(v,u);
lowu=min(lowu,lowv);
if(lowv>pre[u])
{
isbridge[temp]=isbridge[temp^]=;
}
}
else if(v!=fa)
lowu=min(lowu,pre[v]);
}
return lowu;
} void dfs(int u)
{
pre[u]=bcc_cnt;
for(int i=;i<G[u].size();i++)
{
int temp=G[u][i];
if(isbridge[temp]) continue;
int v=edge[temp].v;
if(!pre[v]) dfs(v);
}
} void find_ebbc()
{
bcc_cnt=dfs_clock=;
memset(pre,,sizeof(pre));
memset(isbridge,,sizeof(isbridge)); for(int i=;i<=n;i++)
if(!pre[i]) tarjan(i,-); memset(pre,,sizeof(pre));
for(int i=;i<=n;i++) //计算边—双连通分量
if(!pre[i])
{
bcc_cnt++;
dfs(i);
}
} void rebuild()
{
for(int i=;i<=bcc_cnt;i++) tree[i].clear();
int tot=m<<|;
for(int i=;i<=tot;i+=)
{
if(isbridge[i])
{
int u=edge[i].v, v=edge[i].u;
tree[pre[u]].push_back(make_pair(pre[v],edge[i].c));
tree[pre[v]].push_back(make_pair(pre[u],edge[i].c));
}
}
} int bfs(int u,int flag)
{
for(int i=;i<=bcc_cnt;i++) d[i][flag]=-;
queue<int> Q;
Q.push(u);
d[u][flag]=;
long long max_d=;
int max_u=u;
while(!Q.empty())
{
u=Q.front(); Q.pop();
if(d[u][flag]>max_d) {max_d=d[u][flag];max_u=u;}
for(int i=;i<tree[u].size();i++)
{
int v=tree[u][i].first;
if(d[v][flag]==-)
{
Q.push(v);
d[v][flag]=d[u][flag]+tree[u][i].second;
}
}
}
return max_u;
} int main()
{
//freopen("D:\\input.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) G[i].clear();
for(int i=;i<=m;i++)
{
int u,v; long long w;
scanf("%d%d%lld",&u,&v,&w);
edge[i<<|].u=u; edge[i<<|].v=v; edge[i<<|].c=w;
edge[i<<].u=v; edge[i<<].v=u; edge[i<<].c=w;
G[u].push_back(i<<|);
G[v].push_back(i<<);
}
find_ebbc();
rebuild(); int p=bfs(,);
int q=bfs(p,); //计算出与一端点p的距离
long long length=d[q][];
int z=bfs(q,); long long ans=INF;
long long inx=n+;
for(int i=;i<=n;i++)
{
int cnt=pre[i];
if(d[cnt][]+d[cnt][]!=length) continue;
long long num=max(d[cnt][],d[cnt][]);
if(ans>num)
{
ans=num;
inx=i;
}
}
printf("%lld %lld\n",inx,ans);
}
return ;
}

Gym - 100676H H. Capital City (边双连通分量缩点+树的直径)的更多相关文章

  1. HDU 4612 Warm up (边双连通分量+缩点+树的直径)

    <题目链接> 题目大意:给出一个连通图,问你在这个连通图上加一条边,使该连通图的桥的数量最小,输出最少的桥的数量. 解题分析: 首先,通过Tarjan缩点,将该图缩成一颗树,树上的每个节点 ...

  2. hdu4612 Warm up[边双连通分量缩点+树的直径]

    给你一个连通图,你可以任意加一条边,最小化桥的数目. 添加一条边,发现在边双内是不会减少桥的.只有在边双与边双之间加边才有效.于是,跑一遍边双并缩点,然后就变成一棵树,这样要加一条非树边,路径上的点( ...

  3. hdu 4612 Warm up 双连通缩点+树的直径

    首先双连通缩点建立新图(顺带求原图的总的桥数,事实上因为原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首 ...

  4. hdu4612(双连通缩点+树的直径)

    传送门:Warm up 题意:询问如何加一条边,使得剩下的桥的数目最少,输出数目. 分析:tarjan缩点后,重新建图得到一棵树,树上所有边都为桥,那么找出树的直径两个端点连上,必定减少的桥数量最多, ...

  5. Gym - 100676H Capital City(边强连通分量 + 树的直径)

    H. Capital City[ Color: Black ]Bahosain has become the president of Byteland, he is doing his best t ...

  6. HDU 3686 Traffic Real Time Query System(双连通分量缩点+LCA)(2010 Asia Hangzhou Regional Contest)

    Problem Description City C is really a nightmare of all drivers for its traffic jams. To solve the t ...

  7. 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP)

    layout: post title: 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP) author: "luowentaoaa" catalog: true ...

  8. POJ3177 Redundant Paths(边双连通分量+缩点)

    题目大概是给一个无向连通图,问最少加几条边,使图的任意两点都至少有两条边不重复路径. 如果一个图是边双连通图,即不存在割边,那么任何两个点都满足至少有两条边不重复路径,因为假设有重复边那这条边一定就是 ...

  9. ACM Arabella Collegiate Programming Contest 2015 H. Capital City 边连通分量

    题目链接:http://codeforces.com/gym/100676/attachments 题意: 有 n 个点,m 条边,图中,边强连通分量之间可以直达,即距离为 0 ,找一个点当做首都,其 ...

随机推荐

  1. Fluent Nhibernate Mapping for Sql Views

    Views are mapped the same way tables are mapped except that you should put Readonly() in the mapping ...

  2. 【BZOJ3037/2068】创世纪/[Poi2004]SZP 树形DP

    [BZOJ3037]创世纪 Description applepi手里有一本书<创世纪>,里面记录了这样一个故事……上帝手中有着N 种被称作“世界元素”的东西,现在他要把它们中的一部分投放 ...

  3. R的替换sub和gsub

    sub(pattern, replacement, x, ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE) gsu ...

  4. java 新手入门课程03

    2017.7.6  java 课堂笔记 1.关于分支; if/else 是基于boolean 值的双分支 Switch  基于数字(包括整数 char byte  枚举, 字符串)类型的多分支  方法 ...

  5. linux下的进程,子进程,线程

    1.相同点:(a)二者都具有ID,一组寄存器,状态,优先级以及所要遵循的调度策略.(b) 每个进程都有一个进程控制块,线程也拥有一个线程控制块.(c) 线程和子进程共享父进程中的资源:线程和子进程独立 ...

  6. Magento 2 初探

    进入公司有一小段时间了,虽然自己之前一直从事前端工作,但是基本工作就是做一些国内电商网站的前端工作.在刚进入这家公司时,自己对 magento2 一无所知,尽管上班前看过老大发给我的一些文档资料,但是 ...

  7. Day03 javascript详解

    day03 js 详解 JavaScript的基础 JavaScript的变量 JavaScript的数据类型 JavaScript的语句 JavaScript的数组 JavaScript的函数 Ja ...

  8. editplus的常用快捷键

    小编给大家整理了一些软件的快捷键.http://www.downza.cn/soft/187814.html 创建当前行的副本:Ctrl+J 反转选定文本的大小写:Ctrl+K 选择当前行:Ctrl+ ...

  9. centos 目录结构 快捷键 ls命令,alias别名,so:动态库 a:静态库,环境变量PATH,Ctrl+z 暂停命令,Ctrl+a 光标到行首,Ctrl+e 光标到行尾,Ctrl+u 删除光标前所有字符 Ctrl+r 搜索命 hash命令 Ctrl+左箭头/右箭头 cd命令 第三节课

    centos 目录结构 快捷键 ls命令,alias别名,so:动态库 a:静态库,环境变量PATH,Ctrl+z 暂停命令,Ctrl+a 光标到行首,Ctrl+e 光标到行尾,Ctrl+u 删除光标 ...

  10. js-jquery-从SweetAlert到SweetAlert2

    原文地址:https://github.com/limonte/sweetalert2/wiki/Migration-from-SweetAlert-to-SweetAlert2 1. IE supp ...