• 2017端午欢乐赛——Day1T3(树的直径+并查集)


        //前些天的和jdfz的神犇们联考的模拟赛。那天上午大概是没睡醒吧,考场上忘了写输出-1的情况,白丢了25分真是**。

    题目描述

        小C所在的城市有 n 个供电站,m条电线。相连的供电站会形成一个供电群,那么为了节省材料,供电群是一棵树的形式,也即城市是一个森林的形式(树V个点,V-1条边的无向连通图,森林:若干棵树)。每个供电群中不需要所有供电站都工作,最少只需要一个工作,其余的就都会通过电线收到电,从而完成自己的供电任务。当然,这样会产生延迟。定义两个供电站的延迟为它们之间的电线数量,供电群的最大延迟为其中两两供电站的延迟中最大的那一个,即树的直径。小C现有q个操作,每个操作形如“a b”,表示想要将a所在的供电群中任意一个供电站和b所在的供电群中任意一个供电站之间连一条电线,使得它们成为同一个供电群,并且使这个供电群的最大延迟最小。请输出这个最小的最大延迟。如果 a和 b已经在同一个供电群中,则输出-1,此时不需要进行连线操作。

    ————————————————————————————————————————————————

    输入

        第一行两个整数 n,m (m<n)
        下面 m 行,每行两个整数 a,b,代表 a,b 间有一条无向边
      下面一行一个整数 q
      下面 q 行,每行两个整数 a,b,代表操作

    ————————————————————————————————————————————————

    输出

      输出 q 行,第 i 行一个整数代表操作 i 的答案。

    —————————————————————————————————————————————

    样例输入

      10 7

      1 2

      1 3

      3 4

      3 5

      6 7

      8 9

      8 10

      2

      1 6

      2 8

    ————————————————————————————————————————————————

    样例输出

      4

      4

    ————————————————————————————————————————————————

    样例解释与数据范围

     

     

    ————————————————————————————————————————————————————

        显然树的直径+并查集

        而连接两棵树,若使其连完以后直径最小,则必须连两棵树的直径的中点。

        合并后的直径 max(gg[v],max(gg[u],(gg[v]+1)/2+(gg[u]+1)/2+1));

        可以稍微预处理出树的直径。

        记得判断a和b在同一个供电群的情况。

    —————————————————————————————————————————————————

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<algorithm>
      5 #include<cstring>
      6 const int maxn=1000009; 
      7 using namespace std;
      8 
      9 int n,m,QAQ;//n个供电站,m条电线,Q个操作 
     10 int head[maxn],nxt[maxn<<1],edge[maxn<<1];
     11 int k,flag;
     12 int q[maxn],visited[maxn];
     13 int fa[maxn];
     14 int gg[maxn]; 
     15 
     16 void add(int u,int v)
     17 {
     18     edge[k]=v;
     19     nxt[k]=head[u];
     20     head[u]=k++;
     21 }
     22 
     23 void bfs(int u,int fl)
     24 {
     25     int i,rear=0,frt=0;
     26     q[rear++]=u;
     27     visited[u]=1;
     28     while(frt<rear)
     29     {
     30         int h=q[frt++];
     31         for(i=head[h];i!=-1;i=nxt[i])
     32         {
     33             if(!visited[edge[i]])
     34             {
     35                 visited[edge[i]]=visited[h]+1;
     36                 q[rear++]=edge[i];
     37             }
     38         }
     39     }
     40 
     41     if(!fl){for(i=rear-1;i>=0;i--) visited[q[i]]=0;}
     42     flag=q[rear-1];
     43     
     44 }
     45 
     46 int find(int x)
     47 {
     48     if(fa[x]==x)return x;
     49     else return fa[x]=find(fa[x]);
     50 }
     51 
     52 int maxx(int x,int y)
     53 {
     54     return x>y?x:y;
     55 }
     56 
     57 int main()
     58 {
     59     freopen("connect.in","r",stdin);
     60     freopen("connect.out","w",stdout);
     61     int u,v;
     62     while(scanf("%d%d",&n,&m)!=EOF)
     63     {
     64         memset(head,-1,sizeof(head));
     65         memset(gg,0,sizeof(gg));
     66         memset(visited,0,sizeof(visited));
     67         k=0;
     68 
     69         for(int i=1;i<=n;i++)
     70             fa[i]=i;
     71 
     72         for(int i=0;i<m;i++)
     73         {
     74             scanf("%d%d",&u,&v);
     75             add(u,v);
     76             add(v,u);
     77             u=find(u);
     78             v=find(v);
     79             if(u!=v) fa[u]=v;
     80         }
     81 
     82         for(int i=1;i<=n;i++)
     83             fa[i]=find(i);
     84         for(int i=1;i<=n;i++)
     85         {
     86             if(!visited[i])
     87             {
     88                 bfs(i,0);
     89                 bfs(flag,1);
     90                 gg[fa[i]]=visited[flag]-1;
     91             }
     92         }
     93         cin>>QAQ; 
     94         for(int i=0;i<QAQ;i++)
     95         {
     96             scanf("%d%d",&u,&v);
     97             u=find(u);
     98             v=find(v);
     99             if(u!=v)
    100             { 
    101                 fa[u]=v;
    102                 int mm=maxx(gg[u],gg[v]);
    103                 gg[v]=maxx((gg[v]+1)/2+(gg[u]+1)/2+1,mm);//除以2向上取整 
    104                 gg[u]=0;
    105             } 
    106             if(gg[u]==gg[v]) //同一供电群 
    107             {
    108                 cout<<"-1"<<endl;
    109                 continue;
    110             }
    111             printf("%d
    ",gg[find(u)]);
    112         }
    113     }
    114     fclose(stdin);
    115     fclose(stdout);
    116     return 0;
    117 }
    View Code
  • 相关阅读:
    Beta 冲刺 (5/7)
    Beta 冲刺 (4/7)
    Beta 冲刺 (3/7)
    软件产品案例分析(团队)
    Beta 冲刺 (2/7)
    Beta 冲刺 (1/7)
    BETA 版冲刺前准备
    Alpha事后诸葛(团队)
    设计模式——访问者模式
    设计模式——命令模式
  • 原文地址:https://www.cnblogs.com/Beckinsale/p/6932051.html
Copyright © 2020-2023  润新知