建图方法(邻接矩阵 链式前向星)更新ing

9 篇文章 0 订阅
7 篇文章 0 订阅

u​通常表示起点,​v表示拜访的点,w​表示权值(边的长度之类)。大家代码习惯尽量相同,网上也大致如此。

 

1 .一维数组

int u[105], v[105], w[105];

#include <bits/stdc++.h>
using namespace std;

#define N 105// 节点数
#define MAXM 1005// 边数

/* 输入
6 7

0 2 1
0 4 2
1 4 3
1 5 4
2 3 5
2 4 6
4 5 7
*/
/* 建 图 1-n n个点,m条边 u起点, v终点, w权值;*/
int u[MAXM], v[MAXM], w[MAXM];
int main() {
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=0; i<m; i++) {
		scanf("%d%d%d",&u[i],&v[i],&w[i]);
	}
	for(int i=0; i<m; i++) {
		printf("%d %d %d\n",u[i],v[i],w[i]);
	}
	return 0;
}
/*
输出
0 2 1
0 4 2
1 4 3
1 5 4
2 3 5
2 4 6
4 5 7
*/

 

有点简单,但是遍历以某个点为起点的所有边比较慢,当然可以优化,结构体sort排序二分定位区间,不过也不快。

#include <bits/stdc++.h>
using namespace std;

#define N 105// 节点数
#define MAXM 1005// 边数

/* 输入
6 7

0 2 1
0 4 2
1 4 3
1 5 4
2 3 5
2 4 6
4 5 7
*/
/* 建 图 1-n n个点,m条边 u起点, v终点, w权值;*/
struct Edge {
	int u,v,w;
} edge[MAXM];
bool cmp(Edge a,Edge b) {
	//排序规则,权值从小到大
	return a.w<b.w;
}
int main() {
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=0; i<m; i++) {
		scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
	}
	sort(edge,edge+m,cmp);//权值从小到大
	for(int i=0; i<m; i++) {
		printf("%d %d %d\n",edge[i].u,edge[i].v,edge[i].w);
	}
	return 0;
}
/*
输出
0 2 1
0 4 2
1 4 3
1 5 4
2 3 5
2 4 6
4 5 7
*/ 

 

并查集的其中一个算法就是用这种方法存图(边)。

最小生成树,名字听着高端其实算法并不难。

两种方法一种要用到并查集,不过这应该比较简单

2.二维矩阵(邻接矩阵)

edge[u][v] ​,表示​u到v​的距离,比如设-1​不存在之类,下面第四种就是他的优化

/* 建 图 1-n n个点,m条边 u起点, v终点, w权值;*/
#include <bits/stdc++.h>
using namespace std;

#define N 105// 节点数
#define MAXM 1005// 边数

/* 输入
6 7

0 2 1
0 4 2
1 4 3
1 5 4
2 3 5
2 4 6
4 5 7
*/
/* 建 图 1-n n个点,m条边 u起点, v终点, w权值;*/
int edge[N][N];
int main() {
	int n,m;
	scanf("%d%d",&n,&m);
	memset(edge,-1,sizeof(edge));
	int t=m;
	while(t--) {
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		if(edge[u][v]==-1) {//表示u -> v没有边
			edge[u][v]=w;
			//edge[u][v] = edge[v][u] = w;//存双向边
		}
	}
	for(int i=0; i<n; i++) {
		for(int j=0; j<n; j++) {
			if(edge[i][j]!=-1) {
				printf("%d %d %d\n",i,j,edge[i][j]);
			}
		}

	}
	return 0;
}
/*
输出
0 2 1
0 4 2
1 4 3
1 5 4
2 3 5
2 4 6
4 5 7
*/

 

3.链式前向星(单链表实现的静态邻接表)

常用,我已知最快最优的方法,但是代码略复杂,前期推荐用这个用熟,敲个几十题差不多就熟了。

#include <bits/stdc++.h>
using namespace std;
​
#define N 105// 节点数
#define MAXM 1005// 边数
int first[N], tot = 0;
struct Node {
    int v, w, next;
} edge[MAXM];
void add(int u, int v, int w) {
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].next = first[u];
    first[u] = tot++;
}
int main() {
    tot = 0;
    memset(first, -1, sizeof(first));
    // 初始化一定要记得
    // 加边操作
    int u, v, w;
    scanf("%d%d%d",&u,&v,&w);
    add(u,v,w);
    /* 无向边 再反向加一条即可,add(v,u,w);。
    无向边注意edge[]数组大小是给你的边的两倍,具体题目具体分析
    */
​
    // 遍历以u为起点的所有边
    for(int i = first[u]; ~i; i = edge[i].next) {
        v = edge[i].v, w = edge[i].w; // 适当减短代码
    }
    return 0;
}

 

优点,遍历快,缺点代码量略长,略难理解。

4.邻接表(动态邻接表)

先说缺点,比2略慢一点常数

优点,代码量小,理解使用都很方便

ps:先自行学习​C++ STL 的 vector

#include <bits/stdc++.h>
using namespace std;

#define N 105// 节点数
#define MAXM 1005// 边数

/* 输入
6 7

0 2 1
0 4 2
1 4 3
1 5 4
2 3 5
2 4 6
4 5 7
*/

// 如果没有权值结构体都不用开,或者可以了解下pair相当于一个俩变量结构体,这里不展开了
struct Node {
	int v, w;
} st;
vector <Node> edge[N];

int main() {
	int n, m;
	int u, v, w;
	scanf("%d%d",&n,&m);


	// 加边
	while(m--) {
		scanf("%d%d%d",&u,&st.v,&st.w);
		edge[u].push_back(st);
	}

	// 两种遍历方式,第一种简单的需要起码C++11,除了POJ 基本都支持
	// 遍历以u = 0为起点的所有边
	u = 0;

	for(auto i : edge[u]) { // c++11写法 相当于遍历edge[u]存储的所有元素,i即结构体,非下标,
		v = i.v;
		w = i.w;
		printf("%d %d\n",v,w);
	}

	// 第二种遍历方式,通过遍历下标
	for(int i = u; i < edge[u].size(); ++i) {
		v = edge[u][i].v;
		w = edge[u][i].w;
		printf("- %d %d\n",v,w);
	}
	return 0;
}
/*
输出结果
2 1
4 2
- 2 1
- 4 2
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

nuoyanli

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

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

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

打赏作者

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

抵扣说明:

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

余额充值