题目:点此

我处理这种多组数据的方法被我叫做“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("\n");
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.任何操作(除了输入必须操作)都要在读数据后执行。

posted on 2020-03-13 11:43  eason66  阅读(458)  评论(0编辑  收藏  举报