- 1道编程大题(2021年PAT甲级) 简单的DFS应用
- 15道C语言(来源-2019年878专业课C语言部分真题)
大致题意:
从图中任意一个点选择一个作为起点,每次选择当前下一个点(编号最小),且不重复,问从哪个点出发时,访问的点最多。
输出格式:输出起点(访问最多点数),若不唯一,则输出
编号最小的起点。
先对样例分析:
本题思路:
用邻接表存储图,然后把以i为起点的链表按从小到大排序
然后写一个dfs,从i点出发,当前遍历了dis个结点;
终止条件:访问了更多结点,或者起点更小,
然后递归访问,每次从i结点的链表中选择编号最小的点,作为下一次递归的出发点,然后dis+1即可
AC代码
#include<bits/stdc++.h>
using namespace std;
vector<int>G[105];
int n,m,temps,start,ans=0;
int vis[105];
void dfs(int pos,int dis)
{
//pos:当前出发点
//dis:当前访问的结点个数
if(dis>ans||dis==ans&&temps<start)
{
start=temps;
ans=dis;
}
int size=G[pos].size();
for(int i=0;i<size;i++)
{
if(!vis[G[pos][i]])
{
vis[G[pos][i]]=1;
dfs(G[pos][i],dis+1);
break;
}
}
}
int main()
{
#ifdef ONLINE_JUDGE
#else
{
freopen("1.txt","r",stdin);
}
#endif
cin>>n>>m;
int u,v;
while(m--)
{
cin>>u>>v;
//用邻接表存储图
G[u].emplace_back(v);
G[v].emplace_back(u);
}
for(int i=1;i<=n;i++)
{
//按结点编号从小到大排序
sort(G[i].begin(),G[i].end());
}
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));//初始化所有的点未被访问
temps=i;
vis[i]=1;//标记起点已经被访问
dfs(i,1);
}
cout<<start<<" "<<ans<<endl;
return 0;
}
涉及知识点:与运算
(即:两位同时为“1”,结果才为“1”,否则为0)
选B
理由: 13的二进制为1101,8的二进制为1000
则1101
&xxxx
=1000
则xxxx=1000或1010,即x=8或者10,故选B
注意类函数宏只是简单的替代,而不是函数
选择C
选择D
首先,fun函数的返回值能被x接收,说明fun函数的类型不是void,排除A和B
接着fun(a,&b[0])说明第一个参数类型是int,第二个参数类型是数组
指针p指向数组第一个位置。
a=1 b=3
本题的坑:switch的每一个分支如果没有break,
则会继续执行下一个分支(考研大坑)
本题:a<b 0<1 True 则取c=1
执行两个分支case 1;case 2
a=0,b=1;
①a++;b++;a=1,b=2
②b++; a=1,b=3
所以最后结果为a=1,b=3
注意:case1后面没有break,所以case2也会被执行
因为for循环中间是赋值语句,所以永远为True,所以循环会执行无数次
答案:6 直接画图就ok,没有写出来的都是0
A.表示二级指针
区分一级指针和二级指针
B.表示指向有五个元素的指针
C.表示10个指针组成的数组
所以选择D,全部都是指针
补充知识点
选择A
(int)c=3
(int)d=1
则a%2+(int)c/(int)d=5%2+3/1
=1+3=4
注意:5%2表示5除以2的余数,而不是5除以2
强制类型转换不是四舍五入,而是直接取整数部分
考察递归调用,选择A
(1)n=27时
返回fun(5)*10+2
所以求fun(5)
(2)n=5时
返回fun(1)*10=10
所以fun(5)*10+2
=100+2
=102
答案:-5 -12 -7
简单的模拟(分为三个阶段)
阶段一:
fun(10,5,&a)
a=5-10=-5
则a=-5,b=0,c=0
阶段二:
fun(7,a,&b)
b=a-7=-5-7=-12
则a=-5,b=-12,c=0
阶段三:
fun(a,b,&c)
c=b-a=-12+5=-7
则最后答案为
a=-5,b=-12,c=-7
采用从后向前的分析
最后的可能输出结果t=2*s
其他不可能
则说明前面的s=s+1会执行,说明a>0&&a<b
答案:只要满足a>0且a<b即可,如a=1,b=2