首页 > 其他分享 >「Day 3—深度优先搜索 & 广度优先搜索」

「Day 3—深度优先搜索 & 广度优先搜索」

时间:2024-08-06 21:56:30浏览次数:6  
标签:优先 return int dfs vis 搜索 tot include Day

深度优先搜索

定义

简单来说就是,一条路走到死,不行的话就回溯,继续一条路走到死,直到抵达目标点。

习题

P2052 [NOI2011] 道路修建

思路

首先,看题目对于花费的定义,道路的长度道路两端国家数的差值的绝对值,观察一下这个应该怎么计算,我们很明显能想到树子树大小,于是我们只要知道其中一个的子树大小szie,那么另一个便是n-size,于是乎,花费=d|size-(n-size)|=d|2size-n|,那么用链式前向星存一下各个国家的关系,再dfs去统计花费。

代码
#include<iostream>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;

#define int long long

struct node{
    int to,next,len;
}e[2 * 1000005];
int h[1000005];
int tot = 0;
inline void adge(int x,int y,int len){
    e[++ tot] = (node){y,h[x],len};
    h[x] = tot;
    return;
}

int n,m,ans=0,maxx=-1;
int size[1000005];

void dfs(int x,int f){
	size[x] = 1;
	for(int i = h[x];i != -1;i = e[i].next){
		int v = e[i].to;
		if(v != f){
			dfs(v,x);
			size[x] += size[v];
			ans += e[i].len * abs(n - 2 * size[v]);
		}
	}
}

signed main(){
	memset(h,-1,sizeof(h));
	cin >> n;
	for(int i = 1;i < n;i ++){
		int u,v,w;
		cin >> u >> v >> w;
		adge(u,v,w);
		adge(v,u,w);
	} 
	dfs(1,0);
	cout << ans << "\n";
	return 0;
}

P1434 [SHOI2002] 滑雪

思路

这个题说实话挺水的,就正常dfs,加上一个条件,即当前必须大于下一个,然后用数组记录最大的。但是但是但是,这样会超时4个点,为什么呢,原因是我们做了n * n次dfs,而有些点搜了不止一次,于是我们就想到了记忆化。

代码
#include<iostream>
using namespace std;

int n,m;
int mp[105][105];
int vis[105][105];
int dxy[4][2]={{-1,0},{0,-1},{1,0},{0,1}};

int dfs(int x,int y){
	if(vis[x][y]) return vis[x][y];
	vis[x][y] = 1;
	for(int i = 0;i < 4;i ++){
		int dx = x + dxy[i][0];
		int dy = y + dxy[i][1];
		if(dx > 0 && dy > 0 && dx <= n && dy <= m && mp[x][y] > mp[dx][dy]){
			dfs(dx,dy);
			vis[x][y] = max(vis[x][y],vis[dx][dy] + 1);
		} 
	}
	return vis[x][y];
}

int ans = 0;

int main(){
	
	cin >> n >> m;
	for(int i = 1;i <= n;i ++){
		for(int j = 1;j <= m;j ++){
			cin >> mp[i][j];
		}
	}
	
	for(int i = 1;i <= n;i ++){
		for(int j = 1;j <= n;j ++){
			ans = max(ans,dfs(i,j));
		}
	}
	
	cout << ans << "\n";
	return 0;
}

P2853 [USACO06DEC] Cow Picnic S

思路

首先,这个题看起来很简单,就把所有牧场全dfs一次,如果这个点能到含有奶牛的牧场==k时,这个点就没什么问题,ans++即可,但是但是但是牧场有<=1e4个,边有<=1e5条,所以这样跑肯定有问题,于是我们想到反过来,既然不从点去找牛,就让牛去找牧场,以每个牛所在的位置开始dfs,如果一个点被经过了k次,那么这个点一定就是所以奶牛可到达的地方。理论成立,代码如下:

代码
#include<iostream>
#include<cstring>
using namespace std;

int k,n,m;
int x[100005]; 
struct node{
    int to,next;
}e[2 * 100005];
int h[100005];
bool vis[100005];
int cnt[100005];
int tot = 0;
inline void adge(int x,int y){
    e[++ tot] = (node){y,h[x]};
    h[x] = tot;
    return;
}

void dfs(int x){
	cnt[x] ++;
	for(int i = h[x];i != -1;i = e[i].next){
		int v = e[i].to;
		if(!vis[v]){
			vis[v] = 1;
			dfs(v);
		}
	}
	return;
}

int main(){
	memset(h,-1,sizeof(h));
	cin >> k >> n >> m;
	
	for(int i = 1;i <= k;i ++){
		cin >> x[i];
	}
	
	for(int i = 1;i <= m;i ++){
		int u,v;
		cin >> u >> v;
		adge(u,v);
	}
	for(int i = 1;i <= k;i ++){
		vis[x[i]] = 1;
		dfs(x[i]);
		memset(vis,0,sizeof(vis));
	}
	int ans = 0;
	for(int i = 1;i <= n;i ++){
		if(cnt[i] == k){
			ans ++;
		}
	}
	cout << ans << "\n";
	return 0;
}

P8604 [蓝桥杯 2013 国 C] 危险系数

思路

因为我们要求其关键点个数,所以呢我们可以“人性”一点,每次封锁一个点,跑一遍dfs,如果不能到终点,那么这个点就是关键点。

代码
#include<vector>
#include<iostream>
#include<cstring>
using namespace std;

vector<int> G[1005];
int n,m,ans = 0;
int fx,fy;
bool v1[1005]={0,0};
bool r[1005]={0,0};

void dfs(int x){
	if(v1[x]) return;
	if(r[x]) return;
	v1[x] = 1;
	for(auto v:G[x]){
		dfs(v);
	}
	return;
}

int main(){
	cin >> n >> m;
	for(int i = 1;i <= m;i ++){
		int u,v;
		cin >> u >> v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	cin >> fx >> fy;
	dfs(fx);
	if(v1[fy] == 0){
		cout << "-1\n";
		return 0;
	}
	for(int i = 1;i <= n;i ++){
		if(i == fx || i == fy){
			continue;
		}
		memset(v1,0,sizeof(v1));
		r[i] = 1;
		dfs(fx);
		r[i] = 0;
		if(v1[fy] == 0){
			ans ++;
		}
	}
	cout << ans <<"\n";
	return 0;
}

P1294 高手去散步

思路

首先,用链式前向星存一下信息,为了使他们达到最长的相伴距离,那么就是找一条路,使其边权和最大,如何操作呢,我们可以从n个点各跑一遍dfs,在跑的过程中记录最大的,然后输出即可。

代码
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;

struct node{
    int to,next,len;
}e[10005];
int h[10005];
int vis[10005];
int tot = 0;
inline void adge(int x,int y,int len){
    e[++ tot] = (node){y,h[x],len};
    h[x] = tot;
    return;
}

int n,m,ans=0,maxx=-1;

void dfs(int x){
	for(int i = h[x];i != -1;i = e[i].next){
		int v = e[i].to;
		int w = e[i].len;
		if(vis[v] == 0){
			vis[v] = 1;
			ans += w;
			maxx = max(maxx,ans);
			dfs(v);
			ans -= w;
			vis[v] = 0;
		}
	}
}

int main(){
	memset(h,-1,sizeof(h));
	cin >> n >> m;
	for(int i = 1;i <= m;i ++){
		int u,v,w;
		cin >> u >> v >> w;
		adge(u,v,w);
		adge(v,u,w);
	} 
	for(int i = 1;i <= n;i ++){
		vis[i] = 1;
		dfs(i);
		vis[i] = 0;
	}
	cout << maxx << "\n";
	return 0;
}

P6207 [USACO06OCT] Cows on Skates G

思路

这个题吧,求(1,1)到(r,c)的一条任意路径,我们选择dfs,顺便记录路径。

代码
#include<iostream>
#include<cstdio>
using namespace std;

int n,m;
char mp[150][150];
int pathx[100005];
bool vis[150][150];
int pathy[100005];
int dxy[4][2] = {{1,0},{0,-1},{-1,0},{0,1}};

void dfs(int x,int y,int id){
	pathx[id] = x;
	pathy[id] = y;
	if(x == n && y == m){
		for(int i = 1;i <= id;i ++){
			cout << pathx[i] << " " << pathy[i] << "\n"; 
		}
	}
	for(int i = 0;i < 4;i ++){
		int dx = x + dxy[i][0];
		int dy = y + dxy[i][1];
		if(dx < 1 || dx > n || dy < 1 || dy > m || mp[dx][dy] == '*' || vis[dx][dy]){
			continue;
		}
		vis[dx][dy] = 1;
		dfs(dx,dy,id+1);
	}
}

int main(){
	cin >> n >> m;
	for(int i = 1;i <= n;i ++){
		scanf("%s",mp[i] + 1);
	}
	vis[1][1] = 1;
	dfs(1,1,1);
	return 0;
}

广度优先搜索

定义

别名“宽度优先搜索”,每次向下搜,一层一层搜。

习题

P1330 封锁阳光大学

思路

简单看下,发现无从下手,手动推一下,发现这是个染色问题,于是就bfs+染色,每次选最小的。

代码
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;

struct node{
    int to,next;
}e[500005];
int h[500005],color[500005],cnt[5];
int vis[500005];
int tot = 0;
inline void adge(int x,int y){
    e[++ tot] = (node){y,h[x]};
    h[x] = tot;
    return;
}

int n,m,maxx=-0;

bool bfs(int x){
	queue<int> q;
	q.push(x);
	color[x] = 1;
	cnt[1] = 1,cnt[2] = 0; 
	while(!q.empty()){
		int v = q.front();
		q.pop();
		for(int i = h[v];i != -1;i = e[i].next){
			int t = e[i].to;
			if(color[t] == color[v]){
				return 1;
			}
			if(color[t] == 0){
				color[t] = color[v] % 2 + 1;
				cnt[color[t]] ++;
				q.push(t);
			}
		}
	}
	return 0;
}

int main(){
	memset(h,-1,sizeof(h));
	cin >> n >> m;
	for(int i = 1;i <= m;i ++){
		int u,v;
		cin >> u >> v;
		adge(u,v);
		adge(v,u);
	} 
	for(int i = 1;i <= n;i ++){
		if(color[i]) continue;
		if(bfs(i)){
			cout << "Impossible" << "\n";
			return 0;
		}
		maxx += min(cnt[1],cnt[2]);
	}
	cout << maxx << "\n";
	return 0;
}

标签:优先,return,int,dfs,vis,搜索,tot,include,Day
From: https://www.cnblogs.com/To-Carpe-Diem/p/18346060

相关文章

  • 匿名内部类day10
    /*匿名内部类:语法定义格式:new抽象类/接口(){//要重写的方法}*/abstractclassDemo1{publicabstractvoidfun1();//publicabstractvoidfun2();}//classXXXextendsDemo1{//@Override//......
  • 接口类型的方法调用,使用匿名内部类day10
    /*接口类型的方法调用,使用匿名内部类匿名内部类:语法定义格式:new抽象类/接口(){//要重写的方法}*/interfaceInter1{voidfun1();}//classInter1ImplimplementsInter1{//@Override//publi......
  • 内部类 day10
    /*内部类:将一个类A定义在一个类B中,这个类A称之为内部类分类:成员内部类:将类定义在一个类中的成员位置上局部内部类:将类定义在一个方法中*/classOuter1{inta1=10;privateinta2=11;publicstaticinta3=12;class......
  • 成员内部类day10
    /*内部类常用的修饰符:static被静态的修饰可以直接通过类名.创建对象newOuter2.Inner1()private私有的需要在创建个方法来访问*///classOuter2{//staticinta1=10;//privatestaticinta2=11;//publicstaticinta3......
  • 权限修饰符 day10
    packagecom.shujia.day10.bao5;/*权限修饰符:publicprotected默认的private同一类中√√√√同一包子类,其他类√√√不同包子类......
  • MySQL中DayofWeek与Weekday的区别
    DAYOFWEEK(date):(1-7,周日始,美国人)这个函数返回日期date是一周中的哪一天,范围是1到7。其中,1表示周日,2表示周一,依此类推,7表示周六。这符合美国的日期习惯,即周日是一周的第一天。例如,DAYOFWEEK('2023-03-01')如果这一天是周三,将返回3。WEEKDAY(date):(0-6,周一始)WEEKDAY(......
  • 24-MX-WF day 1 contest solution
    赛时:\(70+50+0+20=140\)\(pts\)题目链接\(A\)\(ball\)首先最朴素的思路肯定是暴力,\(70\)\(pts\)拿下。代码实现#include<bits/stdc++.h>usingnamespacestd;#definelllonglongconstintN=1e7+5;lln,m;lla[N];intmain(){ cin>>n>>......
  • 类,抽象类,接口作为方法参数类型的传参 day10
    /*形式参数基本类型:引用类型:类:当你看到一个类作为方法参数类型的时候,将来调用时需要传递该类及其该类的子类对象抽象类:当你看到一个抽象类作为方法的参数类型的时候,将来调用时需要传递继承该抽象类的具体子类对象......
  • 类,抽象类,接口作为方法的返回值类型 day10
    /*返回值类型基本类型:引用类型:类:当你看到一个类作为方法的返回值类型的时候,将来方法内部应该返回该类或该类的子类对象抽象类:当你看到一个抽象类作为方法的返回值类型的时候,将来方法内部应该返回继承该抽象类的具体子类对象......
  • 自学网络安全day4
    一、定义InternetProtocol,互联网协议,用于实现数据的不可靠面向无连接的通信,实现三层数据封装与IP寻址。(IP协议包含了IP地址)二、原理  ①头部长度/总长度IP头部 标准20字节 最大60字节②DSCP/TOS:区分服务符/服务质量③TTL生存时间IP数据包每经过一“跳”TT......