HYSBZ

来源:互联网 发布:安卓sd卡数据恢复软件 编辑:程序博客网 时间:2024/06/05 17:27


题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1086


题目大意:

中文题面,不多解释。


解题思路:

这个题目要求要按照它的规定将树上一些点分成一些块,每个块的个数在b到3b之间(还有每个省的省会,具体要求看题意)。

首先讲一下思路,其实就是对树进行dfs将结点遍历,将结点加入栈,然后维护一个栈,当栈内的元素符合个数要求的时候就把栈内的元素划分成成一个块即可,

然后是我个人的做题过程,首先刚开始做是直接dfs遍历了一遍树,结果发现正常遍历顺序根本他喵的不对(这明显能找到错误样例),明显差很远。后来仔细想了一下,稍微改变了入栈的顺序,之前是每次dfs开始直接入栈,改成了每次dfs结束再入栈,看起来对了很多,然后交一发wa,后仔细想想发现确实还有错误的例子,当当前的子树内没符合要求的话会直接将另外一颗子树的结点加入当前栈,就造成了省会找不到的情况,遂gg,真的没办法了,上网看了大神的一些博客,感觉处理方法挺巧妙的,首先还是dfs结束后再入栈,但是每次dfs的时候先将当前栈内的元素个数记录一下,然后对于每个子结点dfs完后判断栈内元素的个数-之前的记录个数是否大于b,将多的分成一个块即可,这样就完美解决了之前的问题,省会直接取当前结点即可(自行想想为啥),其次最后将栈内多余的元素全部添加到最后一个块即可,这也某方面印证了为啥这道题的上限是3b个,以下贴代码,


#include <bits/stdc++.h>#define rank ra#define lson rt<<1#define rson rt<<1|1#define pb push_backusing namespace std;typedef long long ll;const int N=10005;int n,m,sz,b,sk;int root[N],fl[N];  //root数组记录每个点属于第几个省 fl数组为每个省省会的结点编号bool vis[N];    //记录当前结点是否被遍历过vector<int> v[N];   //建树stack<int> s;       //维护栈void dfs(int k){    vis[k]=1;    int cnt=s.size();   //遍历前先记录栈内的元素个数    for(int i=0;i<v[k].size();i++)  //遍历树    {        if(!vis[v[k][i]])        {            dfs(v[k][i]);            int gg=s.size();      //记录当前栈的元素            if(gg-cnt>=b)       //若gg-cnt值大于b 符合要求出栈成块            {                fl[++sk]=k;                int zk=gg-cnt;                while(zk--)     //将多余的元素出栈                {                    int g=s.top();                    s.pop();                    root[g]=sk;                }            }        }    }    s.push(k);  //dfs结束后再入栈    return ;}void print(){    printf("%d\n",sk);    for(int i=1;i<=n;i++)        printf("%d ",root[i]);    printf("\n");    for(int i=1;i<=sk;i++)        printf("%d ",fl[i]);    printf("\n");}int main(){    while(scanf("%d%d",&n,&b)!=EOF)    {        int p,q;        //此题不需要初始化        for(int i=1;i<n;i++)        {            scanf("%d%d",&p,&q);            v[p].pb(q);            v[q].pb(p);        }        dfs(1);        while(!s.empty())   //将多余的元素加入最后一个块        {            int g=s.top();            s.pop();            root[g]=sk;        }        print();    //输出答案    }}