欧拉班Day09补充

图联通问题——洛谷P2978

【问题描述】
给定一个无向图,有n个顶点和m条边。
并给定Q次查询,每次给定起点st和终点ed,请判断st和ed是否联通

【输入格式】
第一行有2个数字n、m,用空格隔开,表示有n个顶点,m条边
接下来有m行,每行两个数字u和v,表示一条无向边(u,v)
接下来有Q行,每行两个数字st和ed,用空格隔开,表示起点和终点

【输出格式】
Q行,每行一个数字1或者0,1表示st和ed连通,0表示不连通

【数据范围】
1<=n,m,Q,st,ed<=100

【输入样例1】
5 3
1 2
1 3
4 5
2
2 3
2 4
【输出样例1】
1
0

【输入样例2】
5 4
1 2
5 2
3 4
2 4
2
4 5
3 2
【输出样例2】
1
1

解法1. DFS写法1

int main() {
	cin>>n>>m;
	int Q;
	cin>>Q;
	vector<vector<int> > adj_t(n+1,vector<int>());
	for(int i=0;i<m;i++){
		int u,v;
		cin>>u>>v;
		adj_t[u].push_back(v);
		adj_t[v].push_back(u);
	}
	adjList=adj_t;
	vector<bool> vis_t(n+1,false);
	vis=vis_t;
	while(Q--){
		int st,end;
		cin>>st>>end;
		if(dfs(st,end)){
			cout<<"Y"<<endl;
		}else{
			cout<<"N"<<endl;
		}
		fill(vis.begin(),vis.end(),false);
	}
	return 0;
}

解法2. DFS写法2

int main() {
	cin>>n>>m;
	int Q;
	cin>>Q;
	vector<vector<int> > adj_t(n+1,vector<int>());
	for(int i=0;i<m;i++){
		int u,v;
		cin>>u>>v;
		adj_t[u].push_back(v);adj_t[v].push_back(u);
	}
	adjList=adj_t;
	vector<int> vis_t(n+1,false);
	vis=vis_t;
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			vis[i]=i;
			dfs(i);
		}
	}
	while(Q--){
		int st,end;
		cin>>st>>end;
		if(vis[st]==vis[end]){
			cout<<"Y"<<endl;
		}else{
			cout<<"N"<<endl;
		}
	}
	return 0;
}

解法3. BFS

int main() {
	int x,y;
	cin>>n>>m>>Q;
	for(int i=1;i<=m;i++){
		cin>>x>>y;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	while(Q--){
		//重置
		 memset(vis,0,sizeof(vis));
		 //清空队列
		 queue<int> q_temp;
		 q=q_temp;
		 cin>>st>>ed;
		 //调用广搜函数
		 bool rst=bfs();
		 //输出结果
		 if(rst){
			 cout<<"Y"<<endl;
		 }else{
			 cout<<"N"<<endl;
		 }
	}
	return 0;
}

解法4. Floyd传递闭包

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
#define endl '\n'
bool dp[1001][1001];
//n个顶点,m条边
int n,m,st,ed,Q;
void floyed(){
	for(int k = 1; k <=n; k++) {
		for(int i = 1; i <=n; i++) {
			for(int j = 1; j <= n; j++) {
				dp[i][j] = dp[i][j]||(dp[i][k]&&dp[k][j]);
			}
		}
	}
}
int main() {
	cin >> n >> m>>Q;
	memset(dp,false,sizeof(dp));
	for(int i = 1; i <=m; i++) {
		int p,q;
		cin >> p >> q;
		dp[p][q]=dp[q][p] = true;
	}
	floyed();
	while(Q--){
		 cin>>st>>ed;
		 if(dp[st][ed]){
			 cout<<'Y'<<endl;
		 }else{
			 cout<<'N'<<endl;
		 }
	}
	return 0;
}

解法5. 并查集

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
#define endl '\n'
int n,m;
vector<int> uf;
int _find(int p){
	if(!uf[p]){
		return p;
	}else{
		int root=_find(uf[p]);
		uf[p]=root;
		return root;
	}
}
void un(int p,int q){
	int root1=_find(p),root2=_find(q);
	if(root1!=root2){
		uf[root1]=root2;
	}
}
int main() {
	cin>>n>>m;
	int Q;cin>>Q;
	vector<int> uf_t(n+1,0);
	uf=uf_t;
	for(int i=0;i<m;i++){
		int u,v;cin>>u>>v;
		un(u,v);
	}
	while(Q--){
		int i,j;cin>>i>>j;
		if(_find(i)==_find(j)){
			cout<<"Y"<<endl;
		}else cout<<"N"<<endl;
	}
	return 0;
}

练习2

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int N = 1100;
int a, b, n, m, x, y;
vector<int> g[N];
int vis[N];
void dfs(int x) {
	vis[x] = true;
	for (unsigned i = 0; i < g[x].size(); i++) {
		int v = g[x][i];
		if (vis[v])
			continue;
		dfs(v);
	}
}

练习3:最长路

解法1.DFS

#include <vector>
#include <iostream>
using namespace std;
const int INF=0x6ffffff;
int dis[500001]; //距离记录
int n, m;
struct node {
	int x, y;
};
vector<node> G[500001];
void dfs(int x, int s);
int main() {
	cin >> n >> m;
	int u, v, w;
	for (int i = 1; i <= m; i++) {
		cin >> u >> v >> w;
		G[u].push_back( { v, w });
	}
	fill(dis,dis+n+1,-INF);
	dfs(1, 0);
	if (dis[n]==-INF)
		cout << -1;
	else
		cout << dis[n];
	return 0;
}

解法2. SPFA

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
typedef long long LONG;
using namespace std;
const int MaxN=10001;
LONG INF=6553500;
vector<pair<int,LONG> > adjs[MaxN];
LONG dp[MaxN];
int N,M,ans;
bool vis[MaxN];
//是否可以从p到达写死的target
bool canGo(int p,int& target){
	if(p==target){
		return true;
	}else{
		for(unsigned i=0;i<adjs[p].size();i++){
			int v=adjs[p][i].first;
			if(!vis[v]){
				bool f=canGo(v,target);
				if(f){
					return true;
				}
			}
		}
		return false;
	}
}
void spfa(){
	memset(vis,0,sizeof(vis));
	fill(dp,dp+N+1,-INF);
	queue<int> que;
	que.push(1);
	vis[1]=true;
	dp[1]=0;
	while(!que.empty()){
		int p=que.front();
		que.pop();
		vis[p]=0;
		for(unsigned i=0;i<adjs[p].size();i++){
			int v=adjs[p][i].first;
			if(dp[p]+adjs[p][i].second>dp[v]){
				dp[v]=dp[p]+adjs[p][i].second;
				if(!vis[v]){
					que.push(v);
					vis[v]=1;
				}
			}
		}
	}
	if (dp[N]==-INF)
		cout << -1;
	else
		cout << dp[N];
}
int main() {
	INF*=INF;
	cin>>N>>M;
	for(int i=1;i<=M;i++){
		 int u, v;LONG len;
		 cin >> u >> v >> len;
		 adjs[u].push_back(make_pair(v,len));
	}
	if(!canGo(1,N)){
		cout<<-1<<endl;
		return 0;
	}
	fill(dp,dp+N+1,-INF);
	spfa();
	return 0;
}

练习4:迷宫BFS

#include <iostream>
#include <queue>
#include <string>
using namespace std;
const int N = 1e3 + 7;
int dir[8][2] = {{2,1},{-2,-1},{2,-1},{1,-2},{1, 2},{-1, 2},{-2, 1}, {-1,-2}};
int n, m,sx,sy,ex,ey, dis[N][N], vis[N][N];
string s[N];
struct node{
    int x, y;
};
int bfs(int sx, int sy);
int main(){
    cin >> m >> n;
    for(int i = 0; i < n; i++) cin >> s[i];
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++){
            if(s[i][j] == 'K') sx = i, sy = j;
        }
    cout << bfs(sx, sy);
    return 0;
}
inline bool check(int xx,int yy){
	return xx>=0&&xx<n&&yy>=0&&yy<m;
}

练习5. 细胞

#include <iostream>
using namespace std;
const int N = 110;
char a[N][N];
int vis[N][N];
int n, m;
int dx[4] = { 0, 1, 0, -1 };
int dy[4] = { 1, 0, -1, 0 };
bool check(int x, int y) {
	return x >= 0 && x < n && y >= 0 && y < m;
}
void bfs(int x, int y) {
	
}
int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++) cin >> a[i];
	int ans = 0;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			if(!vis[i][j]&&a[i][j]!='0'){
				bfs(i,j);
				ans++;
			}
		}
	}
	cout << ans << endl;
	return 0;
}

练习6. 联通块数量(八方向)

#include <iostream>
#include <queue>
using namespace std;
char a[112][112];
int n, m, vis[112][112], ans = 0;
int dx[] = { -1, -1, 0, 1, 1, 1, 0, -1 };
int dy[] = { 0, 1, 1, 1, 0, -1, -1, -1 };
struct node {
	int x, y;
};
void bfs(int x, int y);
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++)
			cin >> a[i][j];
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (!vis[i][j] && a[i][j] == 'W') {
				bfs(i, j);
				ans++;
			}
		}
	}
	cout << ans;
	return 0;
}
bool check(int x,int y){
	return x>=1&&x<=n&&y>=1&&y<=m;
}

练习7

比赛T5

在这里插入图片描述
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值