0412备战蓝桥杯,图论复习

1.朴素dijkstra

cpp 复制代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>

using namespace std;
const int N = 510; 

int n,m;
int g[N][N],dist[N];
bool st[N];

int dij(){
	
	memset(dist,0x3f,sizeof dist);
	dist[1] = 0;
	
	for(int i=0;i<n;i++){//n次迭代 
		int t = -1;
		for(int j=1;j<=n;j++)
			if(!st[j] && (t == -1 || dist[j] < dist[t])) 
				t=j;
		st[t] = true;
		for(int j=1;j<=n;j++){
			dist[j] = min(dist[j],dist[t]+g[t][j]);
		} 
	}
	
	if(dist[n] == 0x3f3f3f3f) return -1;
	return dist[n];
}
int main()
{
	cin>>n>>m;
	memset(g,0x3f,sizeof g);
	
	for(int i=0;i<m;i++){
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		g[a][b] = min(g[a][b],c);
	}
	
	int t = dij();
	cout<<t<<endl;
	return 0;
}

2.floyd:初始化自己到自己是0

cpp 复制代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>

using namespace std;
const int N = 210; 

int n,m,k;
int e[N][N];
int st[N];

void floyd(){
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				e[i][j] = min(e[i][j],e[i][k]+e[k][j]);
			}
		}
	}
	return ;
}


int main(){
	cin>>n>>m>>k;
	//memset(e,0x3f,sizeof e);
	for(int i=1;i<=n;i++){
	    for(int j=1;j<=n;j++){
	        if(i==j) e[i][j] = 0;
	        else e[i][j] = 0x3f3f3f3f;
	    }
	}
	while(m--){
		int a,b,c;
		cin>>a>>b>>c;
		e[a][b] = min(e[a][b],c);
	}
	
	floyd();
	
	while(k--){
		int x,y;
		cin>>x>>y;
		
		if(e[x][y] > 0x3f3f3f3f/2) cout<<"impossible"<<endl;
		else cout<<e[x][y]<<endl;
	}
	return 0;
} 

3.prim:点到集合的距离

cpp 复制代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>

using namespace std;
const int N = 510; 

int e[N][N];
int st[N];
int dist[N];//点到集合的距离 
int n,m;
int res;
int cnt;

int prim(){
	memset(dist,0x3f,sizeof dist);
	
	for(int i=0;i<n;i++)//n次迭代
	{
		int t=-1;
		for(int j=1;j<=n;j++){
			if(!st[j] && (t==-1 || dist[j]<dist[t])){
				t=j;
			}
		}
		if(i && dist[t] == 0x3f3f3f3f){
			return 0x3f3f3f3f;//一定要返回无穷大1,不然-1也有可能是答案
		}
		if(i) res+=dist[t];
		st[t] = true;

	/*	st[t] = true;
		cnt++;
		res+=dist[t];
		*/
		for(int j=1;j<=n;j++){
			//用t更新点到集合的距离
			dist[j] = min(dist[j], e[t][j]); 
		}
		
	} 

	return res;
}
int main()
{
	cin>>n>>m;
	memset(e,0x3f,sizeof e);
	while(m--){
		int u,v,w;
		cin>>u>>v>>w;
		if(u==v) continue;
		e[u][v] = e[v][u] = min(e[v][u],w);
	}	
	
	if(prim() == 0x3f3f3f3f) cout<<"impossible"<<endl;
	else cout<<prim()<<endl;
	return 0;
} 
 

4.kruskal:选取最小边进入集合,注意并查集p[x] = find(p[x])

cpp 复制代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>

using namespace std;
const int N = 200010; 
//kruskal从最短边加入集合
int p[N];
int n,m;
struct node{
	int u,v,w;
}; 
node e[N];
int res,cnt;

bool cmp(node aa,node bb){
	return aa.w < bb.w;
}

int find(int x){
	if(p[x] != x) p[x] = find(p[x]);
	return p[x];
}

int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) p[i]=i;
	
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
	//	if(u==v) continue;
		cin>>u>>v>>w;
		e[i] = {u,v,w};
	}	
	sort(e+1,e+m+1,cmp);
	//枚举每条边 
	for(int i=1;i<=m;i++){
		int u=e[i].u;
		int v=e[i].v;
		int w=e[i].w;
		u=find(u);
		v=find(v);
		if(u!=v){
			//如果不在一个连通块
			res += w;
			cnt++;
			p[u] = v;//加入集合 
		} 
	}
	if(cnt<n-1) cout<<"impossible"<<endl;
	else cout<<res<<endl; 
	return 0;
} 
相关推荐
菜还不练就废了34 分钟前
数据结构|并查集
数据结构·算法
heyCHEEMS43 分钟前
[USACO09OCT] Bessie‘s Weight Problem G Java
java·开发语言·算法
凢en1 小时前
NOC科普一
网络·笔记·算法·智能路由器·硬件工程
RanceGru1 小时前
C++——调用OpenCV和NVIDIA Video Codec SDK库实现使用GPU硬解码MP4视频文件
c++·opencv·算法·gpu算力·视频编解码
点云SLAM1 小时前
C++ 中自主内存管理 new/delete 与 malloc/free 完全详解
c++·算法·指针·内存管理·new/delete·malloc/free·内存地址
元亓亓亓2 小时前
LeetCode热题100--53.最大子数组和--中等
数据结构·算法·leetcode
爱凤的小光2 小时前
图漾官网Sample_V1版本C++语言完整参考例子---单相机版本
开发语言·c++·数码相机
青瓦梦滋2 小时前
【语法】C++的继承
开发语言·c++
ttk2193 小时前
【算法练习】归并排序和归并分治
数据结构·c++·算法·排序算法
情报员0073 小时前
Java练习6
java·算法·排序算法