11.图的深度优先搜索——②强化

例子1:连通块的数量
在这里插入图片描述
在这里插入图片描述
思路:
在这里插入图片描述

#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
vector<int> G[20005];//!!!size问题
bool vis[20005];//!!!size问题
void dfs(int u) {
    vis[u] = true;
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (!vis[v]) {
            dfs(v);
        }
    }
}
int main() {
    freopen("block.in","r",stdin);
    freopen("block.out","w",stdout);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(!vis[i]){//边判断有无访问过,边进行搜索
            cnt++;
            dfs(i);
        }
    }
    cout<<cnt<<endl;
    return 0;
}

例子2:下午茶时间
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
思路:
在这里插入图片描述

#include<iostream>
#include<cstdio>
using namespace std;
int f[50005];
int getf(int v)
{
	return f[v]==v ? v:getf(f[v]); 
}
void merge(int v,int u)
{
	int t1=getf(v);
	int t2=getf(u);
	if(t1!=t2)
	f[t2]=t1;
	return;
}
int main()
{
    freopen("tea.in","r",stdin);
    freopen("tea.out","w",stdout);
	int i,x,y,n,m,s;
	while(scanf("%d %d %d", &n,&m,&s)!=EOF)
	{
		for(i=1; i<=n; i++)
	    f[i]=i; 
		for(i=1; i<=m;i++)
		{
			scanf("%d %d", &x,&y);
			merge(x,y);
		}
		for(i=1; i<=s; i++)
		{
			scanf("%d %d", &x,&y);
			if(getf(x)==getf(y))
			printf("Y\n");
			else
			printf("N\n");
		}
	}
	return 0;
}

例子3:家谱
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
思路:
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> son[100005];
int ans[100005];
bool vis[100005];
int dfs(int x){//dfs函数返回x节点的直系后代数
    int res=0;
    for(int i=0;i<son[x].size();i++){
        res+=dfs(son[x][i]);//遍历x节点的所有儿子,求出所有的儿子的直系后代数
    }
    ans[x]=res;
    return res+1;//x的孩子的直系后代数+1
}
int main(){
    freopen("family.in","r",stdin);
    freopen("family.out","w",stdout);
    cin>>n;
    for(int i=0;i<n-1;i++){
        int x,y;
        cin>>x>>y;
        son[x].push_back(y);//x的孩子为y
        vis[y]=true;//y有父亲,标记为true,表示不是根节点
    }
    int u;
    for(int i=1;i<=n;i++){//找根节点
        if(!vis[i]){
            u=i;
            break;
        }
    }
    dfs(u);
    for(int i=1;i<=n;i++){
        cout<<ans[i]<<endl;
    }
    return 0;
}

例子4:联合权值(选做)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
思路:
在这里插入图片描述

#include<bits/stdc++.h>

#define ll long long
#define MAXN 500010
#define N 201
#define INF 0x3f3f3f3f
#define gtc() getchar()

using namespace std;

template <class T>
inline void read(T &s){
	s = 0; T w = 1, ch = gtc();
	while(!isdigit(ch)){if(ch == '-') w = -1; ch = gtc();}
	while(isdigit(ch)){s = s * 10 + ch - '0'; ch = gtc();}
	s *= w;
}

template <class T>
inline void write(T x){
    if(x < 0) putchar('-'), x = -x;
	if(x > 9) write(x/10);
    putchar(x % 10 + '0');
}

const int mod = 10007;
struct node{
	int y, ne;
}e[MAXN];
int lin[MAXN], len = 0;
inline void add(int x, int y){
	e[++len].y = y, e[len].ne = lin[x], lin[x] = len;
}

int n;
int d[MAXN];
int sum[MAXN];
int all = 0, ans = 0;

void bfs(int x){
	int fmx = 0, smx = 0;
	int sum1 = 0, sum2 = 0;
	for(int i = lin[x]; i; i = e[i].ne){
		int y = e[i].y;
//		printf("%d ", y);
		sum1 = (sum1 + d[y]) % mod;
		sum2 = (sum2 + d[y] * d[y]) % mod; 
		if(d[y] > fmx){
			smx = fmx, fmx = d[y];
		}
		else if(d[y] > smx) smx = d[y];
	}
//	puts("");
	ans = max(ans, fmx * smx);
	sum1 = sum1 * sum1 % mod; 
	all +=  (sum1 - sum2 + mod) % mod;
}
int main()
{
    freopen("link.in","r",stdin);
    freopen("link.out","w",stdout);
	read(n);
	int x, y;
	for(int i = 1; i < n; ++i){
		read(x), read(y);
		add(x, y), add(y, x);
	}
	for(int i = 1; i <= n; ++i) read(d[i]);
	for(int i = 1; i <= n; ++i) bfs(i);
	all %= mod; 
	cout << ans << ' ' << all << endl;
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值