zoukankan      html  css  js  c++  java
  • Gym

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

    题意:

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

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

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

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 using namespace std;
     11 
     12 const int maxn=1e5+5;
     13 const long long INF =1e15+5;
     14 typedef pair<long long,long long> pll;
     15 
     16 struct Edge
     17 {
     18     long long u,v,c;
     19 }edge[maxn<<2];
     20 
     21 int n,m;
     22 int pre[maxn],isbridge[maxn<<4],bcc_cnt,dfs_clock;
     23 long long d[maxn][2];
     24 vector<int> G[maxn];
     25 vector<pll> tree[maxn];
     26 
     27 int tarjan(int u,int fa)
     28 {
     29     int lowu=pre[u]=++dfs_clock;
     30     for(int i=0;i<G[u].size();i++)
     31     {
     32         int temp=G[u][i];
     33         int v=edge[temp].v;
     34         if(!pre[v])
     35         {
     36             int lowv=tarjan(v,u);
     37             lowu=min(lowu,lowv);
     38             if(lowv>pre[u])
     39             {
     40                 isbridge[temp]=isbridge[temp^1]=1;
     41             }
     42         }
     43         else if(v!=fa)
     44             lowu=min(lowu,pre[v]);
     45     }
     46     return lowu;
     47 }
     48 
     49 void dfs(int u)
     50 {
     51     pre[u]=bcc_cnt;
     52     for(int i=0;i<G[u].size();i++)
     53     {
     54         int temp=G[u][i];
     55         if(isbridge[temp])   continue;
     56         int v=edge[temp].v;
     57         if(!pre[v])  dfs(v);
     58     }
     59 }
     60 
     61 void find_ebbc()
     62 {
     63     bcc_cnt=dfs_clock=0;
     64     memset(pre,0,sizeof(pre));
     65     memset(isbridge,0,sizeof(isbridge));
     66 
     67     for(int i=1;i<=n;i++)
     68         if(!pre[i])   tarjan(i,-1);
     69 
     70     memset(pre,0,sizeof(pre));
     71     for(int i=1;i<=n;i++)             //计算边—双连通分量
     72         if(!pre[i])
     73         {
     74             bcc_cnt++;
     75             dfs(i);
     76         }
     77 }
     78 
     79 void rebuild()
     80 {
     81     for(int i=1;i<=bcc_cnt;i++)  tree[i].clear();
     82     int tot=m<<1|1;
     83     for(int i=3;i<=tot;i+=2)
     84     {
     85         if(isbridge[i])
     86         {
     87             int u=edge[i].v, v=edge[i].u;
     88             tree[pre[u]].push_back(make_pair(pre[v],edge[i].c));
     89             tree[pre[v]].push_back(make_pair(pre[u],edge[i].c));
     90         }
     91     }
     92 }
     93 
     94 int bfs(int u,int flag)
     95 {
     96     for(int i=1;i<=bcc_cnt;i++)  d[i][flag]=-1;
     97     queue<int> Q;
     98     Q.push(u);
     99     d[u][flag]=0;
    100     long long max_d=0;
    101     int max_u=u;
    102     while(!Q.empty())
    103     {
    104         u=Q.front(); Q.pop();
    105         if(d[u][flag]>max_d)  {max_d=d[u][flag];max_u=u;}
    106         for(int i=0;i<tree[u].size();i++)
    107         {
    108             int v=tree[u][i].first;
    109             if(d[v][flag]==-1)
    110             {
    111                 Q.push(v);
    112                 d[v][flag]=d[u][flag]+tree[u][i].second;
    113             }
    114         }
    115     }
    116     return max_u;
    117 }
    118 
    119 
    120 int main()
    121 {
    122     //freopen("D:\input.txt","r",stdin);
    123     int T;
    124     scanf("%d",&T);
    125     while(T--)
    126     {
    127         scanf("%d%d",&n,&m);
    128         for(int i=1;i<=n;i++)  G[i].clear();
    129         for(int i=1;i<=m;i++)
    130         {
    131             int u,v; long long w;
    132             scanf("%d%d%lld",&u,&v,&w);
    133             edge[i<<1|1].u=u; edge[i<<1|1].v=v; edge[i<<1|1].c=w;
    134             edge[i<<1].u=v; edge[i<<1].v=u; edge[i<<1].c=w;
    135             G[u].push_back(i<<1|1);
    136             G[v].push_back(i<<1);
    137         }
    138         find_ebbc();
    139         rebuild();
    140 
    141         int p=bfs(1,0);
    142         int q=bfs(p,0);   //计算出与一端点p的距离
    143         long long length=d[q][0];
    144         int z=bfs(q,1);
    145 
    146         long long ans=INF;
    147         long long inx=n+1;
    148         for(int i=1;i<=n;i++)
    149         {
    150             int cnt=pre[i];
    151             if(d[cnt][0]+d[cnt][1]!=length)  continue;
    152             long long num=max(d[cnt][0],d[cnt][1]);
    153             if(ans>num)
    154             {
    155                 ans=num;
    156                 inx=i;
    157             }
    158         }
    159         printf("%lld %lld
    ",inx,ans);
    160     }
    161     return 0;
    162 }
  • 相关阅读:
    Samba文件服务器详细配置步骤
    chkconfig命令详解
    rdesktop的使用方法
    CentOs中yum安装LAMP+PHPMYADMIN
    YUM源
    Centos下设置VNC为3389端口
    vnc服务的安装与配置
    rdesktop的使用
    nginx 日志分割
    程序员私活网汇总
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6897386.html
Copyright © 2011-2022 走看看