P7215 JOISC2020 首都

P7215 JOISC2020 首都

点分治好题。

思路

求出当前分治中心,把当前分治中心作为首都,暴力跑需要合并多少个城市,不能越过上一层分治中心。

如果越过了上一个分治中心,把上一个分治中心作为首都也可以起到相同的效果,就没有必要再跑一次了。

时间复杂度 O(nlogn)

CODE

#include<bits/stdc++.h>
using namespace std;

const int maxn=2e5+5;

struct Edge
{
    int tot;
    int head[maxn];
    struct edgenode{int to,nxt;}edge[maxn*2];
    inline void add(int x,int y)
    {
        tot++;
        edge[tot].to=y;
        edge[tot].nxt=head[x];
        head[x]=tot;
    }
}T;

int n,ans;
int col[maxn],fa[maxn],bol[maxn];

vector<int>vec[maxn];

int siz[maxn];
bool cut[maxn],book[maxn],vis[maxn];
inline void dfs_siz(int u)
{
    book[u]=true;siz[u]=1;
    for(int i=T.head[u];i;i=T.edge[i].nxt)
    {
        int v=T.edge[i].to;
        if(book[v]||cut[v]) continue;
        dfs_siz(v);siz[u]+=siz[v];
    }
    book[u]=false;
}
inline int dfs_rt(int u,const int tot)
{
    book[u]=true;int ret=u;
    for(int i=T.head[u];i;i=T.edge[i].nxt)
    {
        int v=T.edge[i].to;
        if(book[v]||cut[v]) continue;
        if(siz[v]*2>=tot){ret=dfs_rt(v,tot);break;}
    }
    book[u]=false;return ret;
}
int cnt;
inline void bfs(int g)
{
    queue<int>que;
    for(auto v:vec[col[g]])
    {
        que.push(v),vis[v]=true;
        if(bol[v]!=g) {cnt=n;return ;}
    }
    while(!que.empty())
    {
        int u=que.front();que.pop();
        if(vis[fa[u]]) continue;
        for(auto v:vec[col[fa[u]]])
        {
            que.push(v),vis[v]=true;
            if(bol[v]!=g) {cnt=n;return ;}
        }
        cnt++;
    }
}
inline void dfs2(int u,const int g)
{
    book[u]=true;vis[u]=false;bol[u]=g;
    for(int i=T.head[u];i;i=T.edge[i].nxt)
    {
        int v=T.edge[i].to;
        if(book[v]||cut[v]) continue;
        fa[v]=u;
        dfs2(v,g);
    }
    book[u]=false;
}
inline void dfs(int u)
{
    dfs_siz(u);int g=dfs_rt(u,siz[u]);cut[g]=true;
    fa[g]=g;dfs2(g,g);cnt=0;bfs(g);ans=min(ans,cnt);
    for(int i=T.head[g];i;i=T.edge[i].nxt)
    {
        int v=T.edge[i].to;
        if(cut[v]) continue;
        dfs(v);
    }
}

int main()
{
    scanf("%d%d",&n,&ans);
    for(int i=1;i<n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        T.add(u,v),T.add(v,u);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&col[i]);
        vec[col[i]].emplace_back(i);
    }
    dfs(1);
    printf("%d",ans);
}
posted @   彬彬冰激凌  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示