E - Anton and Tree(dfs shrinkage + DFS find the longest diameter)

Topic: Give n n points, n-1 edges constitute a spanning tree, each point has two colors, black and white, each change of color can make the adjacent points of the same color change color, to find the minimum number of changes in color.

Analysis: Because each change of color can change the color of the adjacent points with the same color, so the adjacent points with the same color can be condensed into a point, rebuilt the map, and form a tree with black and white points. Let the diameter of the tree (the farthest distance between any two points) be d, because each change of color will make it the same color with the adjacent points, so the operation of taking the points on the diameter of the tree has a total of d+1. Because the dots are black and white, at least (d+1)/2 dots can change the whole picture to the same color. At first I couldn't figure it out, but then I found out. Some points on the branches and leaves will change color when the points on the diameter change, and the length of the points on the branches and leaves can not exceed the points on the diameter, otherwise it will be the diameter.

#include <iostream>
#include<vector>
#include<stdio.h>
#define N 200005
using namespace std;

vector<int >g[N],gc[N];  //g is the original graph and gc is the graph after the contraction point
int visit[N],col[N],comp[N],dp[N]; //dp stores the farthest distance from the point to any point in the graph, and comp is the point of the graph after the point belongs to the contraction point.
int ans=0;
void dfs(int u,int c,int rt)//Shrinkage point operation
{
    if(visit[u] || col[u]!=c)
        return;
    visit[u]=1;
    comp[u]=rt;
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        dfs(v,c,rt);
    }
}
void DFS(int u,int fa)//Finding the Length of Diameter
{
    int mx=0,mmx=0; //mx is the farthest distance from a point to any point in a graph, and mmx is the next farthest distance.
    for(int i=0;i<gc[u].size();i++)
    {
        int v=gc[u][i];
        if(v==fa)  //Prevent him from traversing back to the parent node
            continue;
        DFS(v,u);
        mmx=max(mmx,dp[v]+1);
        if(mmx > mx) swap(mx,mmx);
    }
    dp[u]=mx;
    ans=max(ans,mx+mmx);//The furthest distance of a graph is equal to the furthest distance of a point plus the next furthest distance
}
int main()
{
    int n,u,v;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&col[i]);
    }
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    int cnt=1;
    for(int i=1;i<=n;i++)
    {
        if(!visit[i]) dfs(i,col[i],cnt++);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<g[i].size();j++)
        {
            int v= g[i][j];
            if(comp[v]!=comp[i])
            {
                gc[comp[i]].push_back(comp[v]);
            }
        }
    }
    DFS(1,1);
    printf("%d\n",(ans+1)/2);
}










Posted by altis88 on Tue, 12 Feb 2019 17:39:18 -0800