欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

结题报告--洛谷P3915

程序员文章站 2022-04-16 09:26:28
题目:点此。 我处理这种多组数据的方法被我叫做“mains法”,就是先假设只有一组数据,写一个代码,然后把那个main函数改成mains,最后写一个真正的main函数。 这个“真正的”main函数一般有两种 1.告诉你数据组数: 1 int main(){ 2 int t; 3 cin >> t; ......

 

题目:点此

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