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