2019 Niu Ke Summer Multi-School Training Camp (Cuarta sesión) Una reunión

Descripción del título

Se acaba de construir una nueva ciudad. Hay  nortelugares interesantes numerados por números positivos del 1 al norte.

Para ahorrar recursos, solo n-1se construyen exactamente  caminos para conectar estos  nortelugares interesantes. Cada camino conecta dos lugares y se tarda 1 segundo en viajar entre los puntos finales de cualquier camino.

Hay una persona en cada uno de los lugares numerados  x_1, x_2 ... x_ky han decidido reunirse en un lugar para comer. Se preguntan cuál es el tiempo mínimo necesario para que se reúnan en ese lugar. (El tiempo requerido es el tiempo máximo para que cada persona llegue a ese lugar).

Ingrese la descripción 

Primera línea dos enteros positivos, n, k: el número de lugares y personas.

Para cada una de las siguientes líneas n − 1, hay dos enteros a, b que representan una carretera que conecta el lugar a y b. Se garantiza que estas carreteras conectan todos los n lugares.

En la siguiente línea hay k enteros positivos diferentes  x_1, x_2 ... x_kseparados por espacios. Estos son los números de lugares en los que se encuentran las personas.

Descripción de salida 

Un número entero no negativo: el tiempo mínimo para que las personas se reúnan.

Entrada de ejemplo 

4 2
1 2
3 1
3 4
2 4

Salida de muestra 

2

Explicación 

Pueden reunirse en el lugar 1 o 3.

Observaciones 

1 \ leqslant n \ leqslant 10 ^ 5

La idea principal:

En un árbol, hay varios nodos, y alguien solicita seleccionar un nodo para que todos puedan reunirse en este nodo. El tiempo de reunión se define como el tiempo más largo que tardan todos en llegar al nodo. Se requiere el tiempo mínimo de reunión.

Análisis:

Considere las dos personas que están más alejadas, entonces el punto medio de los dos caminos es el punto de encuentro de todas las personas, lo que puede garantizar el tiempo mínimo de reunión. Esto es similar a encontrar el diámetro de un árbol. El resultado es que el diámetro del árbol se divide por 2 y se redondea. El BFS se usa dos veces para encontrar el diámetro, pero debe tenerse en cuenta que solo se usa la profundidad del nodo de la persona para actualizar el diámetro durante el recorrido, por lo que se obtiene la distancia máxima entre los nodos de la persona.

Vea el código para una explicación específica.

#include<stdio.h>

#include<string.h>

#include<queue>

#define MAX 200005

using namespace std;

int head[MAX];

int vis[MAX];//在BFS中,标记当前节点是否已经用过 

int dis[MAX];//记录最长距离(即节点的深度) 

int signal[MAX];//标志哪些点有人 

int n,m,ans;

int sum;//记录有人的节点之间最长路径的长度 

int lst;//记录最长路径的终点节点 

struct node

{

    int u,v,w;

    int next;

}edge[MAX];

void add(int u,int v,int w)//向邻接表中加边 

{

    edge[ans].u=u;

    edge[ans].v=v;

    edge[ans].w=w;

    edge[ans].next=head[u];

    head[u]=ans++;

}

void getmap()

{

    int i,j;

    int a,b,c;

    ans=0;

    memset(head,-1,sizeof(head));

    while(m--)

    {

        scanf("%d%d",&a,&b);

        add(a,b,1);

        add(b,a,1);

    }

}

void bfs(int beg)

{

    queue<int>q;

    memset(dis,0,sizeof(dis));

    memset(vis,0,sizeof(vis));

    int i,j;

    while(!q.empty())

        q.pop();

    lst=beg;//终点初始化为起点 

    sum=0;

    vis[beg]=1;

    q.push(beg);

    int top;

    while(!q.empty())

    {

        top=q.front();

        q.pop();

        for(i=head[top];i!=-1;i=edge[i].next)

        {

            if(!vis[edge[i].v])

            {

                dis[edge[i].v]=dis[top]+edge[i].w;//更新节点深度 

                vis[edge[i].v]=1;

                q.push(edge[i].v);

                if(signal[edge[i].v]&&sum<dis[edge[i].v])//只有当该节点有人,才会用该节点的深度去更新最长路径的值 

                {

                    sum=dis[edge[i].v];
                    
                    lst=edge[i].v;

                } 

            }

        }

    }

}

int main()

{


    int n,k,i; 
	
    scanf("%d%d",&n,&k);
	
    m=n-1;
	
    getmap();
    
    int a;
	
    for(i=1;i<=k;i++)
    {
		
	scanf("%d",&a); 
		 
	signal[a]=1;
		
    } 

    bfs(a);//从某一个有人的节点开始,搜索最长路径的一个端点 

    bfs(lst);//搜索另一个端点 

    printf("%d\n",(sum+1)/2);//最长路径的一半上取整 

    return 0;

}

 

30 artículos originales publicados · ganó 5 · 900 visitas

Supongo que te gusta

Origin blog.csdn.net/qq_42840665/article/details/97802396
Recomendado
Clasificación