一、图的存储
1、邻接矩阵:就是用一个二维数组存啦~但是只能用于较小的图
**一定要判重
#include<bits/stdc++.h>
using namespace std;
const int N = 5e3 + 2;// 邻接矩阵最多就5e3
int mp[N][N];
int main()
{
int n, m;// 点数、边数
cin >> n >> m;
for(int i = 0; i < m; i++){
int u, v;
cin >> u >> v;
mp[u][v] = mp[v][u] = 1;// 无向图
//mp[u][v] = 1;// 有向图
}
return 0;
}
2、邻接表存图(不会aaa)
3、链式前向星
#include<bits/stdc++.h> //链式前向星存图(有边权)+dfs
using namespace std;
const int N=1e5+2,M=5e5+2;
struct node{
int v,w,nxt;
};
node e[M];
int head[N],cnt;
int n,m;
void add(int u,int v,int w){
e[cnt].w=w; e[cnt].v=v;
e[cnt].nxt=head[u]; head[u]=cnt++;
}
// bool vis[N];
// void dfs(int u){
// cout<<u<<" ";
// vis[u]=1;
// for(int j=head[u];j!=-1;j=e[j].nxt){
// int v=e[j].v;
// if(!vis[v]) dfs(v);
// }
// }
int main(){
memset(head,-1,sizeof head);
cin>>n>>m;
int u,v,w;
for(int i=0;i<m;i++){
cin>>u>>v>>w;
add(u,v,w);
}
// dfs(1);
for(int i=1;i<=n;i++){
cout<<i<<"的邻接点有:";
for(int j=head[i];j!=-1;j=e[j].nxt){
int v=e[j].v;
cout<<v<<" "<<e[j].w<<";";
}
cout<<endl;
}
return 0;
}
4、vector存图
(1)无边权:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e4 + 10;
int n, e;
vector<int>g[N];
bool vis[N];
void dfs(int s){
cout << s << " ";
vis[s] = 1;
for(int i = 0; i < g[s].size(); i++){
if(!vis[g[s][i]]){
dfs(g[s][i]);
}
}
}
int main()
{
cin >> n >> e;
for(int i = 0; i < e; i++){
int u, v;
cin >> u >> v;
g[u].push_back(v);// 有向边
//g[v].push_back(u);// 无向边
}
for(int i = 0; i < n; i++) {
sort(g[i].begin(), g[i].end());
}
for(int i = 0; i < n; i++){
if(!vis[i]){
dfs(i);
}
}
return 0;
}
(2)有边权
**我的评价是不如用链式前向星那种简单
const int N = 1e5 + 10;
struct node{
int v, w;
};
node add(int v, int w){
node e; e.v = v; e.w = w; return e;
}
vector<node>g[N];
void addedge(int u, int v, int w){
g[u].push_back(add(v, w));
g[v].push_back(add(u, w));
}
二、图的遍历
1、dfs && bfs
#include<bits/stdc++.h>
using namespace std;
// vector存图
const int N = 1e5+10;
vector<int> a[N];
queue<int>q;
int n, e;
bool st[N];
void dfs(int s){
cout << s << " ";
st[s] = 1;
for(int j = 0; j < a[s].size(); j++){
if(!st[a[s][j]]){
dfs(a[s][j]);
}
}
}
void bfs(int s){
memset(st, 0, sizeof(st));// 一定!一定!!不要忘了清空!!!
q.push(s);
cout << s << " ";
st[s] = 1;
while (q.size())
{
int t = q.front(); q.pop();
for(int j = 0; j < a[t].size(); j++){
int x = a[t][j];
if(!st[x]){
cout << x << " ";
st[x] = 1;
q.push(x);
}
}
}
}
int main()
{
cin >> n >> e;
int u, v;
for(int i = 0; i < e; i++){
cin >> u >> v;
a[u].push_back(v);
}
for(int i = 0; i < n; i ++){
sort(a[i].begin(), a[i].end());
}
for(int i = 0; i < n; i++){// 因为不一定是连通图!
if(!st[i]){
dfs(i);
}
}
cout << endl;
bfs(0);
return 0;
}
三、最小生成树
1、prime算法
#include<bits/stdc++.h>
using namespace std;
// 邻接矩阵存图
// prime算法
const int N = 550, INF = 0x3f3f3f3f;
int mp[N][N];
int dis[N];
int vis1[N], vis2[N];
int num;
int prime(){
memset(dis, INF, sizeof(dis));
dis[1] = 0;
int ans = 0;
for(int i = 1; i <= num; i++){
int t = 0;
for(int j = 1; j <= num; j++){
if(!vis1[j] && dis[t] > dis[j]) t = j;
}
vis1[t] = 1;
ans += dis[t];
for(int j = 1; j <= num; j++){
if(!vis1[j]) dis[j] = min(dis[j], mp[t][j]);
}
}
return ans;
}
int main()
{
int u, v, w;
memset(mp, INF, sizeof(mp));
while(cin >> u >> v >> w){
if(u == 0 && v == 0 && w == 0) break;
vis2[u] = 1; vis2[v] = 1;
mp[u+1][v+1] = mp[v+1][u+1] = min(mp[u+1][v+1], w);
}
for(int i = 0; i < N; i++){
if(vis2[i]) num++;// 统计点的个数
}
cout << prime() << endl;
return 0;
}
2、kruskal
#include<bits/sdc++.h>
using namespace std;
const int M=1e5+10,N=1e5+10;
struct node{
int u,v,w;
bool operator <(const node &b)const{
return w<b.w;
}
}e[M];
int n,m;
//priority_queue<node> q;
int fa[N];
int find(int x){
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) fa[i]=i;
int u,v,w;
for(int i=0;i<m;i++)
{
cin>>u>>v>>w;
e[i].u=u,e[i].v=v,e[i].w=w;
// q.push(e[i]);
}
sort(e,e+m);
int cnt=0;
int ans=0;
for(int i=0;i<m;i++){
node p=e[i];
int x=find(p.u),y=find(p.v);
if(x!=y){
cnt++;
ans+=p.w;
}
if(cnt==n-1) break;
}
cout<<ans;
return 0;
}
四、最短路
单源点
1、①dijkstra算法(朴素版)
②dijkstra算法(优化版)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10, M = 5e5 + 10;
const int INF = 0x3f3f3f3f;
int n, m, s, cnt;
int head[N], dist[N];
bool st[N];
struct node{
int v, w, nxt;
}e[M];
// 链式前向星存图T_T
void add(int u, int v, int w){
e[cnt].w = w; e[cnt].v = v;
e[cnt].nxt = head[u];head[u] = cnt++;
}
typedef pair<int, int>pll;
priority_queue<pll, vector<pll>, greater<pll> > q;
void dijstra(){
memset(dist, 0x3f, sizeof(dist));
dist[s] = 0;
q.push({0, s});
while(q.size()){
pll tmp = q.top();q.pop();
int d = tmp.first, v = tmp.second;
if(st[v]) continue;
st[v] = 1;
for (int i = head[v]; i != -1; i = e[i].nxt){
int j = e[i].v;
if(dist[j] > d + e[i].w){
dist[j] = d + e[i].w;
q.push({dist[j], j});
}
}
}
}
int main()
{
memset(head, -1, sizeof(head));
cin >> n >> m;
s = 0;
int u, v, w;
for (int i = 0; i < m; i++){
cin >> u >> v >> w;
add(u, v, w);
}
dijstra();
for(int i = 1; i < n; i++){
if(dist[i] == INF) continue;
else cout << dist[i] << " ";
}
return 0;
}
**关于pair:C++ pair的基本用法总结(整理)_sevencheng798的博客-CSDN博客_c++ pair
任意两点
2、Floyd算法(时间复杂度高,为O(n^3))
const int N = 302;// 最多差不多就300
int mp[N][N];
void Floyed(){
for(int k = 1; k <= n; k++){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
}
}
}
}
五、拓扑排序
1、判断
bool topo(){
int num = 0;
queue<int>q;
for(int i = 1; i <= n; i++){
if(indegree[i] == 0){
q.push(i);
}
}
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = 0; i < g[u].size(); i++){
int v = g[u][i];
indegree[v]--;
if(indegree[v] == 0){
q.push(v);
}
}
g[u].clear();
num++;
}
if(num == n) return 1;
else return 0;
}