100198H Royal Federation

传送门

题目大意

国家有N个城市,任意城市可以到达任意城市,是一棵树。国王要给这些城市分省份。每个省份最少M个城市,最多3M个城市。每个省有一个首府,首府不一定是这个省的城市,只是首府到这个省各个城市只能经过这个省的城市。给出N和M,求分配方案,输出有多少个省,各个城市属于哪个省,每个省的首府是哪个城。(一个城可以是多个城的首府)(无解则输出0)

分析

我们不难想到先进行dfs,将每一块满足要求的划分出来,然后再将某个点的儿子中没被划分出来的点为根的子树几个拼成一个,使得它也成为合法的一个省。但是我们再想一想可以发现,这样划分最后可能会多出一些没有归属的点,而这些点最多为M-1个,所以我们只需要控制之前划分出来的每个省城市数不超过2M+1,然后最后将没有归属的省加到最后一个建立的省就行了。详见代码。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>

using namespace std;

#define ct cout
#define el endl
#define fi first
#define se second
#define pf printf
#define li long long
#define pb push_back
#define mkp make_pair
#define vi vector<int>
#define y1 y12345678909
#define rii register int
#define pii pair<int,int>
#define ck(x) cout<<x<<endl;
#define uli unsigned long long
#define clr(x) memset(x,0,sizeof(x))
#define sp cout<<"---------------------------------------------------"<<endl

inline int ra(){
      int _x=0,_f=1;char _s=getchar();
      while(!isdigit(_s)){if(_s=='-')_f=-1;_s=getchar();}
      while(isdigit(_s)){_x=(_x<<3)+(_x<<1)+(_s-'0');_s=getchar();}
      return _x*_f;
}
inline li lra(){
      li _x=0,_f=1;char _s=getchar();
      while(!isdigit(_s)){if(_s=='-')_f=-1;_s=getchar();}
      while(isdigit(_s)){_x=(_x<<3)+(_x<<1)+(_s-'0');_s=getchar();}
      return _x*_f;
}

//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//

vi v[201000];
int siz[201000],n,m,sum,belong[201000],head[201000];
inline void cor(int x,int col,int fa){
      for(int i=0;i<v[x].size();i++)
        if(v[x][i]!=fa&&!belong[v[x][i]]){
            belong[v[x][i]]=col;
            cor(v[x][i],col,x);
      }
      return;
}
inline void dfs(int x,int fa){
      int i,j,k;
      siz[x]=1;
      for(int i=0;i<v[x].size();i++)
        if(v[x][i]!=fa){
          dfs(v[x][i],x);
          if(!belong[v[x][i]])siz[x]+=siz[v[x][i]];
        }
      if(siz[x]>=m&&siz[x]<=2*m+1){
          head[++sum]=x;
          cor(x,sum,fa);
          belong[x]=sum;
          return;
      }
      if(siz[x]<m)return;
      int ns=0,la=-1;
      for(int i=0;i<v[x].size();i++)
          if(v[x][i]!=fa&&!belong[v[x][i]]){
            ns+=siz[v[x][i]];
            if(ns>=m){
              head[++sum]=x;
                for(int j=la+1;j<=i;j++)
                  if(v[x][j]!=fa&&!belong[v[x][j]]){
                belong[v[x][j]]=sum;
                cor(v[x][j],sum,x);
              }
                la=i;
                ns=0;
            }
        }
      for(int i=la+1;i<v[x].size();i++)
        if(v[x][i]!=fa&&!belong[v[x][i]]){
          belong[v[x][i]]=sum;
          cor(v[x][i],sum,x);
        }
      belong[x]=sum;
      return;
}
int main(){
      freopen("royal.in","r",stdin);
      freopen("royal.out","w",stdout);
      clr(belong);
      clr(siz);
      clr(head);
      int i,j,k;
      n=ra(),m=ra();
      for(i=1;i<n;i++){
          int x,y;
          x=ra(),y=ra();
          v[x].pb(y),v[y].pb(x);
      }
      dfs(1,0);
      pf("%d
",sum);
      if(sum){
          for(i=1;i<=n;i++)
          if(!belong[i])
            belong[i]=sum;
        for(i=1;i<=n;i++)pf("%d ",belong[i]);
        puts("");
        for(i=1;i<=sum;i++)pf("%d ",head[i]);
        puts("");
      }
      return 0;
}
原文地址:https://www.cnblogs.com/yzxverygood/p/9378087.html