搜索类题目的练习

上周我们练习了大量的搜索题目对搜索的题目有了基本的了解,知道了什么情况下用深搜什么情况下用广搜,这一周还是练习搜索,继续加深对搜索的理解。

上周主要练习的是点的行进,就是单纯对点进行搜索,这周则是进一步通过图来进行搜索,虽然上一周也有部分涉及图,但是本质还是点的行进,通过这星期的练习我总结,首先这分两部分。

一、有向图的遍历搜索

例如这题:

P2853 [USACO06DEC]Cow Picnic S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

K(1≤K≤100)只奶牛分散在N(1≤N≤1000)个牧场.现在她们要集中起来进餐.牧场之间有M(1≤M≤10000)条有向路连接,而且不存在起点和终点相同的有向路.她们进餐的地点必须是所有奶牛都可到达的地方.那么,有多少这样的牧场呢?

通过题目我们可以知道题目中说是必须每个奶牛必须全部到达,我们可以想到用深搜找到所有的可能,其次我们发现,其实每个牧场之间是有关系,而奶牛被关在牧场里,这其实和点的行进是有相似的地方的,但是着重点并不是点,而是牧场之间的关系,我们可以把他的关系列出来

 

 利用上图我们利用vector动态数组储存起来,之所以用vector是因为方便我们列写插入关系表,

 for(int i=1;i<=m;i++) 
    {
        cin>>a>>b;
        vec[a].push_back(b);
    }

只是有几个地方需要注意,我们dfs的是奶牛其他地方基本是相同的

void dfs(int x)
{
     vis[x]=1;  m[x]++;
     for(int i=0;i<vec[x].size();i++)
         if(!vis[vec[x][i]])
             dfs(vec[x][i]);
}

因此我们总结包含关系的是可以用无权有向图来深搜的

例如:P4017 最大食物链计数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

也是这个类型,通过题目我们知道,存在生产者与消费者两种物种,之间有着吃与被吃的关系,因此也是一种有向图,也是可以用vector动态数组储存,但这题有个特别的地方其实他是有值的,但是本质上还是有向图,因为生产者是不吃消费者的,因此我们以消费者为vector的一维标,列写和上面一样的关系图:

方法 

 方法还是和上面的类似:

 for(int i=1;i<=m;i++) 
    {
        cin>>a>>b;
        vec[b].push_back(a);
ifxiaofei[a]=true;//判断是消费者还是生产者,因为是以消费者进行的搜索
    }

然后接下来就是深搜了,注意的是这个是有权值的,注意权值是要继承累加的:

int dfs(int x)
{ 
if(!vec[x].size()) 
return qz[x]=1;//生产者权值是1
int sum=0;
for(int i=0;i<vec[x].size();i++)
{ int next=vec[x][i];
   if(qz[x])
   sum+=qz[x];
else 
dfs(next);
sum%=mod;

}

return qz[x]=sum;

}

然后我们从消费者开始深搜就行了,

然后接下来我们会发现还有另一部分题,同样是两个地点间有路径问题,但是并不是单向的,,也就是无向图的问题,

二、无向图,

例如:P1294 高手去散步 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目描述:

鳌头山上有n个观景点,观景点两两之间有游步道共m条。

我们知道,对于观景点我们可以从1到3,也可以从3到1,那么我们在列写这类无向图时实际上就是再多加几条路,多搜索一条而已,本质上其实没什么区别,

for(int i=1;i<=m;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		s[a].push_back(b);
		s[b].push_back(a);
	}

像这样,反向存一条路就行了,还有要注意的是,这个也是有权值的,深搜时注意储存就行了,题目和上面的基本类似,无非是反过来多走几条路。

        通过对搜索的练习加深了对搜索的理解,还发现,许多知识其实是相连的,就像我们常说的知识固然重要,但是重要的是如何灵活的运用,把知识灵活的转化,这种图的遍历其实与之前的记忆化搜索一样,且这个也是之后拓扑排序的基础,因此我认为对题目的练习是很有必要的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Assault boy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值