• [loj3176]景点划分


    不妨设$ale ble c$,那么相当于要找到两个大小至少为$a$和$b$的连通块(连通块可以通过删除度最小的点变小)
    以一个点为根建出dfs树并对以下情况分类讨论:
    1.存在一个节点满足$max(max_{son}(sz[son]),n-sz[k]+s)<a$(其中$sz[k]$表示k子树大小,$s$表示删除$k$后仍然与根联通的点个数),那么必然无解(两个连通块必然都需要经过$k$)
    2.不存在,那么必然有解,且可以通过以下方法构造:
    (1)找到任意一个满足$sz[k]ge a$且$max_{son}(sz[son])<a$的点$k$
    (2)若$n-sz[k]+sge b$,将在$k$子树中且删去$k$后无法与根联通的$x$加入$S_{a}$,对于剩下的子树不断加入$S_{a}$直到$S_{a}$大小不小于$a$,然后剩下的点归入$S_{b}$
    由于$max_{son}(sz[son])<a$,因此$S_{a}$的大小最多为$2a$,那么$|S_{b}|=n-2age n-a-c=b$
    (3)若$n-sz[k]+s<b$,由于$ble lfloor frac{n}{2} floor$,因此$sz[k]>lceil frac{n}{2} ceil+s>b$,同时$n-sz[k]+sge a$(否则无解),那么交换$a$和$b$后用同样的方法即可
    (代码中有一些小问题,可以通过随机根解决QAQ)
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005 
     4 struct ji{
     5     int nex,to;
     6 }edge[N<<2];
     7 pair<int,int>a[11];
     8 int E,r,n,m,x,y,flag,head[N],sz[N],dfn[N],low[N],tot[N],ans[N];
     9 void add(int x,int y){
    10     edge[E].nex=head[x];
    11     edge[E].to=y;
    12     head[x]=E++;
    13 }
    14 void update(int k,int p){
    15     if ((!a[p].first)||(ans[k]))return;
    16     a[p].first--;
    17     ans[k]=a[p].second;
    18     for(int i=head[k];i!=-1;i=edge[i].nex)
    19         if (edge[i].to)update(edge[i].to,p);
    20 }
    21 void dfs(int k,int fa){
    22     int mx=0,s=0;
    23     sz[k]=1;
    24     dfn[k]=low[k]=++x;
    25     for(int i=head[k];i!=-1;i=edge[i].nex)
    26         if (!sz[edge[i].to]){
    27             dfs(edge[i].to,k);
    28             if (flag)return;
    29             sz[k]+=sz[edge[i].to];
    30             low[k]=min(low[k],low[edge[i].to]);
    31             if (low[edge[i].to]<dfn[k])s+=sz[edge[i].to];
    32         }
    33         else{
    34             if (edge[i].to!=fa)low[k]=min(low[k],dfn[edge[i].to]);
    35             edge[i].to=0;
    36         }
    37     if ((mx<a[1].first)&&(sz[k]>=a[1].first)){
    38         flag=2;
    39         if (n-sz[k]+s<a[1].first){
    40             flag=1;
    41             return;
    42         }
    43         if (n-sz[k]+s<a[2].first)swap(a[1],a[2]);
    44         ans[k]=a[1].second;
    45         a[1].first--;
    46         for(int i=head[k];i!=-1;i=edge[i].nex)
    47             if ((edge[i].to)&&(low[edge[i].to]>=dfn[k]))update(edge[i].to,1);
    48         for(int i=head[k];i!=-1;i=edge[i].nex)
    49             if ((edge[i].to)&&(low[edge[i].to]<dfn[k]))update(edge[i].to,1);
    50         update(r,2);
    51         for(int i=1;i<=n;i++)
    52             if (!ans[i])ans[i]=a[3].second;
    53     }
    54 }
    55 int main(){
    56     srand(time(0));
    57     scanf("%d%d",&n,&m);
    58     r=rand()%n+1;
    59     for(int i=1;i<=3;i++){
    60         scanf("%d",&a[i].first);
    61         a[i].second=i;
    62     }
    63     sort(a+1,a+4);
    64     memset(head,-1,sizeof(head));
    65     for(int i=1;i<=m;i++){
    66         scanf("%d%d",&x,&y);
    67         add(x+1,y+1);
    68         add(y+1,x+1);
    69     }
    70     dfs(r,0);
    71     for(int i=1;i<=n;i++)printf("%d ",ans[i]);
    72 } 
    View Code
  • 相关阅读:
    523. Continuous Subarray Sum
    517. Super Washing Machines
    516. Longest Palindromic Subsequence
    486. Predict the Winner
    467. Unique Substrings in Wraparound String
    474. Ones and Zeroes
    语法小结
    互评作业:使用数组
    466. Count The Repetitions
    1052 卖个萌 (20 分)
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13440863.html
Copyright © 2020-2023  润新知