bzoj1086 [SCOI2005] Royal Federation (tree block)

Title Link

analysis:
An interesting question
At the beginning of looking at this problem, I felt it was not difficult, so I took YY as an approach:
If the size of a subtree meets the conditions, the whole dfs tree is divided into a "province", and the capital is the root of the subtree
If there are any remaining points, they must be concentrated in the root part
We can divide them into a new province as the case may be, or merge them into the last province

It's done. WA, of course
Later, it was considered that if there is only two layers of a tree and there are many sons, it may not be possible to consider the whole subtree

Positive solution:
We should take advantage of this condition: the provincial capital is not necessarily within the province
Open a stack, dfs the whole tree
If the size s of several subtrees of node x add up to meet the requirements,
Divide these subtrees into one province. The provincial capital is the current node x
As for those subtrees that can't reach the requirements, we will count their size on x and go back to the previous level

In the end, we may have a few points left
In this way, the size of the provincial capital we have divided must not exceed 2*B
The last remaining node must not exceed B (or another province can be divided in the process of backtracking)
We put the remaining points directly into the final provinces

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstring>

using namespace std;

const int N=1005;
struct node{
    int x,y,nxt;
};
node way[N<<1];
int n,B,st[N],tot=0;
int S[N],tt=0,ans[N],wh[N],cnt=0,size[N],sz[N];
bool ff=0;

void add(int u,int w)
{
    tot++;
    way[tot].x=u; way[tot].y=w; way[tot].nxt=st[u];st[u]=tot;
    tot++;
    way[tot].x=w; way[tot].y=u; way[tot].nxt=st[w];st[w]=tot;
}

void solve(int now,int fa)
{
    S[++tt]=now;                            //Stack 
    for (int i=st[now];i;i=way[i].nxt)
        if (way[i].y!=fa)
        {
            solve(way[i].y,now);
            if (size[now]+size[way[i].y]>=B) {
                sz[++cnt]=size[now]; size[now]=0;
                ans[cnt]=now;
                while (S[tt]!=now)
                    wh[S[tt--]]=cnt;
            }
            else size[now]+=size[way[i].y];
        }
    size[now]++;                          //Add root and backtrace 
}

int main()
{
    scanf("%d%d",&n,&B);
    for (int i=1;i<n;i++)
    {
        int u,w;
        scanf("%d%d",&u,&w);
        add(u,w);
    }
    if (B>n) {
        printf("0");
        return 0;
    } 

    solve(1,0);
    for (int i=cnt;i>=1;i--)
        if (tt+sz[i]<=3*B)
        {
            while (tt) wh[S[tt--]]=i;
            break;
        } 

    printf("%d\n",cnt);
    for (int i=1;i<=n;i++) printf("%d ",wh[i]);
    puts("");
    for (int i=1;i<=cnt;i++) printf("%d ",ans[i]);

    return 0;
}

Posted by dnice on Fri, 01 May 2020 07:19:04 -0700