zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    socket编程技巧(2)发送缓冲区和接收缓冲区的设置时机
    socket编程技巧(1)tcp接收接口(变长数据定长数据)的编写实例
    libnet介绍与分析
    TCP的6大标示符号
    数据帧中常见协议类型
    C语言中offsetof宏的应用
    ip欺骗(原始套接字系列九)
    ARP欺骗(原始套接字系列八)
    包分析(原始套接字七)
    了解Javascript中函数作为对象的魅力
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9378087.html
Copyright © 2011-2022 走看看