• 结题报告--洛谷P3915


     

    题目:点此

    我处理这种多组数据的方法被我叫做“mains法”,就是先假设只有一组数据,写一个代码,然后把那个main函数改成mains,最后写一个真正的main函数。

    这个“真正的”main函数一般有两种 1.告诉你数据组数:

    1 int main(){
    2     int t;
    3     cin >>  t;
    4     for(int i=0;i<t;i++){
    5         mains();
    6     }
    7     return 0;
    8 }

    2.不告诉你数据组数:

    1 int main(){
    2     int *|*;//*|*表示根据实际情况会发生变化,这里*|*表示mains中第一个读入的数据,放在main函数里读入
    3     while(cin >> *|*){
    4         mains(*|*);//*|*用参数的形式告诉mains
    5     }
    6 }

    好了,进入正题


    这道题我的思路是:先读入数据,建立一棵类似于邻接表存储的树(这样方便调 试,而且貌似也没有坏处),然后判断n%k是否等于0,不等直接NO,return 0! 等于继续。进行深搜,首先找到下一个访问的顶点进行访问,然后判断返回值(那个结点是该分组的第几个节点) 是否大于k或=-1(=-1说明已经无法划分),返回-1,否则判断是否等于k,若等于说明已有一组,无需继续配对 否则将ans变量加上这个返回值,该节点访问完毕后return ans,ans初始值为1,不为0。 最后如果根节点返回值不为k,输出Yes,否则NO。

    (为什么是不等于?我不知道,不等于就AC,等于就爆零) 代码:

     1 #include <cstdio>
     2 #include <vector>
     3 using namespace std;
     4 bool color[100000]={true};
     5 vector <int> tree[100000];
     6 int k;
     7 int dfs(int now){
     8     color[now]=false;
     9     int number=1;
    10     for(int i=0;i<tree[now].size();i++){
    11         if(color[tree[now][i]]){
    12             int a=dfs(tree[now][i]);
    13             if(a>k||a==-1){
    14                 return -1;
    15             }
    16             if(a==k){
    17                 continue;
    18             }
    19             number+=a;
    20         }
    21     }
    22     return number;
    23 }
    24 int mains(){
    25     int n;
    26     scanf("%d %d",&n,&k);
    27     for(int i=0;i<n;i++){
    28         tree[i].clear();
    29         color[i]=true;
    30     }
    31     for(int i=0;i<n-1;i++){
    32         int x,y;
    33         scanf("%d %d",&x,&y);
    34         x--;
    35         y--;
    36         tree[x].push_back(y);
    37         tree[y].push_back(x);
    38     }
    39     if(n%k!=0){
    40         puts("NO");
    41         return 0;
    42     }
    43     if(dfs(1)==k){
    44         puts("YES");
    45     }
    46     else{
    47         puts("NO");
    48     }
    49     return 0;
    50 }
    51 int main(){
    52     int t;
    53     scanf("%d",&t);
    54     for(int i=0;i<t;i++){
    55         mains();
    56         //puts("
    ");
    57     }
    58     return 0;
    59 }
    代码

    补充:

    在你已熟练printf和scanf的时候,不要用cin、cout,用printf、scanf,不然cin数据一大,光读数据就会 TLE,还有如果你会且熟练getchar()或cin.get()读入整数的话,就用它,应为有些时候数据很大,scanf也 会TLE,所以就要用到它。

    附录:

    用getchar或cin.get()读入数据的基本模板:

     1 int read()//视需要可变成long long,unsighed long long……
     2 {
     3     int s=0,w=1;//返回值类型变了,s也要变,w不用变
     4     char ch=getchar();
     5     while(ch<'0'||ch>'9')
     6     {
     7         if(ch=='-')
     8             w=-1;
     9         ch=getchar();
    10     }
    11     while(ch>='0'&&ch<='9')
    12         s=s*10+ch-'0',ch=getchar();
    13     return s*w;
    14 }

     

    (这次调整了一下顺序,犯的错误和收获在后面)

    犯的错误:

    1.dfs如果不满足条件应该return不是exit,因为如果是单测试数据,这样做是可以的,可是它有多组数据,这样做会直接结束程序,导致后面的测试数据没法输出答案。

    2.tree邻接表没进行初始化(clear)。

    3.用vector实现的邻接表不用头节点。

    4.exit改成return后输出NO的语句没去掉。

    5.判断是否整除的语句应该放在读数据的后面,不然数据就没读完,后面的数据会被认为是下一组数据的开始。

    6.color数组没初始化。

    7.第十行是tree[now]不是tree[i]。

    收获:

    1.尽量不用exit,除非不是在做题(别忘了我还在开发游戏)

    2.遇到多测试数据的题目,在mains里,三省代码:变量初始化了吗??数组初始化了吗??stl容器初始化了吗??

    3.添加头节点的时候,问自己:需要吗??若需要,写dfs时,再问一遍:循环时是否访问了头节点??

    4.该要改全面。

    5.任何操作(除了输入必须操作)都要在读数据后执行。

  • 相关阅读:
    Codeforces Round #545 (div 1.)
    THUSC 2017 大魔法师
    loj #6216. 雪花挂饰
    [NOI Online #2 提高组]涂色游戏
    [NOI Online #2 提高组]子序列问题
    [NOI Online #1 入门组]跑步
    备战noip week7
    [NOI Online #3 提高组]优秀子序列
    20201017校测
    springboot基于maven多模块项目搭建(直接启动webApplication)
  • 原文地址:https://www.cnblogs.com/eason66-blog/p/P3915-luogu.html
Copyright © 2020-2023  润新知