Gym - 100676H H. Capital City (边双连通分量缩点+树的直径)
2017-05-24 09:40
357 查看
https://vjudge.net/problem/Gym-100676H
题意:
给出一个n个城市,城市之间有距离为w的边,现在要选一个中心城市,使得该城市到其余城市的最大距离最短。如果有一些城市是强连通的,那么他们可以使用传送门瞬间到达。
思路:
因为强连通时可以瞬移,因为是无向图,所以计算边双连通分量然后重新建图,这样,也就不存在环了。
接下来,计算一下树的直径,因为中心城市肯定选在树的直径上,这样才有可能使最大的边最短。
题意:
给出一个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+5; const long long INF =1e15+5; typedef pair<long long,long long> pll; struct Edge { long long u,v,c; }edge[maxn<<2]; int n,m; int pre[maxn],isbridge[maxn<<4],bcc_cnt,dfs_clock; long long d[maxn][2]; vector<int> G[maxn]; vector<pll> tree[maxn]; int tarjan(int u,int fa) { int lowu=pre[u]=++dfs_clock; for(int i=0;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^1]=1; } } else if(v!=fa) lowu=min(lowu,pre[v]); } return lowu; } void dfs(int u) { pre[u]=bcc_cnt; for(int i=0;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=0; memset(pre,0,sizeof(pre)); memset(isbridge,0,sizeof(isbridge)); for(int i=1;i<=n;i++) if(!pre[i]) tarjan(i,-1); memset(pre,0,sizeof(pre)); for(int i=1;i<=n;i++) //计算边—双连通分量 if(!pre[i]) { bcc_cnt++; dfs(i); } } void rebuild() { for(int i=1;i<=bcc_cnt;i++) tree[i].clear(); int tot=m<<1|1; for(int i=3;i<=tot;i+=2) { 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=1;i<=bcc_cnt;i++) d[i][flag]=-1; queue<int> Q; Q.push(u); d[u][flag]=0; long long max_d=0; 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=0;i<tree[u].size();i++) { int v=tree[u][i].first; if(d[v][flag]==-1) { 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=1;i<=n;i++) G[i].clear(); for(int i=1;i<=m;i++) { int u,v; long long w; scanf("%d%d%lld",&u,&v,&w); edge[i<<1|1].u=u; edge[i<<1|1].v=v; edge[i<<1|1].c=w; edge[i<<1].u=v; edge[i<<1].v=u; edge[i<<1].c=w; G[u].push_back(i<<1|1); G[v].push_back(i<<1); } find_ebbc(); rebuild(); int p=bfs(1,0); int q=bfs(p,0); //计算出与一端点p的距离 long long length=d[q][0]; int z=bfs(q,1); long long ans=INF; long long inx=n+1; for(int i=1;i<=n;i++) { int cnt=pre[i]; if(d[cnt][0]+d[cnt][1]!=length) continue; long long num=max(d[cnt][0],d[cnt][1]); if(ans>num) { ans=num; inx=i; } } printf("%lld %lld\n",inx,ans); } return 0; }
相关文章推荐
- Gym 100712H(边双联通+树的直径)
- codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点
- Gym - 100781A Adjoin the Networks 无向图的直径、连通性
- Gym 100712H(边双联通+树的直径)
- Gym 100712H(边双联通+树的直径)
- codeforces gym-101755 I-Guess the Tree 交互题、分治、树的直径
- Gym 100712H(边双联通+树的直径)
- Gym 100712H(边双联通+树的直径)
- Gym 100712H(边双联通+树的直径)
- Gym 100712H(边双联通+树的直径)
- Gym 100712H(边双联通+树的直径)
- Gym - 100676H Capital City(边强连通分量 + 树的直径)
- Gym 100712H(边双联通+树的直径)
- codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径
- Gym-100781A 【树的直径 + 思维】
- codeforces GYM 100781A【树的直径】
- Gym - 101522B树的直径
- Gym 100712H Bridges(桥+缩点+树的直径)
- Gym - 100676H Capital City(边强连通分量 + 树的直径)
- Gym 100712H(边双联通+树的直径)