当前位置:首页 » 《随便一记》 » 正文

图的基本算法_Ja_king_的博客

10 人参与  2022年05月31日 14:33  分类 : 《随便一记》  评论

点击全文阅读


图的基本算法

    • bellman-ford算法
    • dijkstra算法
    • Floyd算法
    • spfa算法
    • prim算法(最小生成树)
    • 拓扑排序
    • 图的dfs和bfs

bellman-ford算法

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=510,M=10010;
int dist[N],backup[N];
int n,m,k;
struct edge{
    int a,b,w;
}edges[M];
int bellman_ford(){
    memset(dist,0x3f,sizeof(dist));
    dist[1]=0;
    for(int i=0;i<k;i++){
        memcpy(backup,dist,sizeof dist);
        for(int j=1;j<=m;j++){
            int a=edges[j-1].a,b=edges[j-1].b,w=edges[j-1].w;
            dist[b]=min(dist[b],backup[a]+w);
        }
    }
    //if(dist[n]>0x3f3f3f3f/2)return -1;
    return dist[n];
}
int main(){
    cin>>n>>m>>k;
    for(int i=0;i<m;i++){
        int a,b,w;
        cin>>a>>b>>w;
        edges[i]={a,b,w};
    }
    int t=bellman_ford();
    if(t>0x3f3f3f3f/2)puts("impossible");
    else cout<<t;
    return 0;
}

dijkstra算法

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N=510;

int g[N][N];    //为稠密阵所以用邻接矩阵存储
int dist[N];    //用于记录每一个点距离第一个点的距离
bool st[N];     //用于记录该点的最短距离是否已经确定

int n,m;

int Dijkstra()
{
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    for(int i=0;i<n;i++){
        int t=-1;
        for(int j=1;j<=n;j++){
            if(!st[j]&&(t==-1||dist[t]>dist[j]))
                t=j;
        }
        st[t]=true;
        for(int u=1;u<=n;u++){
            dist[u]=min(dist[u],dist[t]+g[t][u]);
        }
    }
    if(dist[n]==0x3f3f3f3f)return -1;
    return dist[n];
}
int main()
{
    cin>>n>>m;

    memset(g,0x3f,sizeof g);    //初始化图 因为是求最短路径
                                //所以每个点初始为无限大

    while(m--)
    {
        int x,y,z;
        cin>>x>>y>>z;
        g[x][y]=min(g[x][y],z);     //如果发生重边的情况则保留最短的一条边
    }

    cout<<Dijkstra()<<endl;
    return 0;
}

Floyd算法

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=210;
int g[N][N];
int m,n,k;
int main(){
    cin>>n>>m>>k;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            if(i==j)g[i][j]=0;
            else g[i][j]=999999;
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b]=min(g[a][b],c);
    }
    for(int v=1;v<=n;v++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(g[i][j]>g[i][v]+g[v][j])
                    g[i][j]=g[i][v]+g[v][j];
            }
        }
    }
    while(k--){
        int x,y;
        cin>>x>>y;
        if(g[x][y]>= 900000)printf("impossible\n");
        else cout<<g[x][y]<<endl;
    }
    return 0;
}

spfa算法

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e5+10;
int e[N],ne[N],h[N],w[N],idx;
int n, m;
int dist[N];
bool st[N];
void add(int a,int b,int c){
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int spfa(){
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    queue<int>q;
    q.push(1);
    st[1]=true;
    while(!q.empty()){
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i]){
            int j=e[i];
            if(dist[j]>dist[t]+w[i]){
                dist[j]=dist[t]+w[i];
                if(!st[j]){
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    //if(dist[n]==0x3f3f3f3f)return -1;
    return dist[n];
}
int main(){
    memset(h,-1,sizeof(h));
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    int t=spfa();
    if(t==0x3f3f3f3f)puts("impossible");
    else cout<<t;
    return 0;
}

prim算法(最小生成树)

#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

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

int prim(){
    memset(dist,0x3f,sizeof dist);
    int ans=0;
    for(int i=1;i<=n;i++){
        int t=-1;
        for(int j=1;j<=n;j++){
            if(!st[j]&&(t==-1||dist[j]<dist[t]))
                t=j;
        }
        st[t]=true;
        if((i-1)&&dist[t]==0x3f3f3f3f)return 0x3f3f3f3f;

        if(i-1) ans+=dist[t];

        for(int v=1;v<=n;v++){
            dist[v]=min(dist[v],g[t][v]);
        }

    }
    return ans;
}

int main(){ 
    memset(g,0x3f,sizeof g);
    cin >> n >> m;
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b]=g[b][a]=min(g[a][b],c);
    }
    int t=prim();
    if(t==0x3f3f3f3f)cout<<"impossible";
    else cout<<t;
    return 0;
}

拓扑排序

#include<iostream>
#include<cstring>
using namespace std;
const int N=1e5+10;
int e[N],ne[N],h[N],idx;
int n,m;
int q[N],d[N];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool topsort(){
    int hh=0,tt=-1;
    for(int i=1;i<=n;i++){
        if(d[i]==0)q[++tt]=i;
    }
    while(hh<=tt){
        int t=q[hh++];
        for(int i=h[t];i!=-1;i=ne[i]){
            int j=e[i];
            d[j]--;
            if(d[j]==0) q[++tt]=j;
        }
    }
    return tt==n-1;
}
int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b;
        cin>>a>>b;
        add(a,b);
        d[b]++;
    }
    if(topsort()){
        for(int i=0;i<n;i++){
            cout<<q[i]<<' ';
        }
    }
    else{
        cout<<-1;
    }
    return 0;
}

图的dfs和bfs

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<queue>
#include<stdio.h>
using namespace std;

//dfs求岛屿面积
const int N = 1100;
int arr[N][N], book[N][N], sum = 1, m, n, x, y;
void dfs(int x, int y) {
	int dx[4] = { 1,0,-1,0 };
	int dy[4] = { 0,1,0,-1 };
	int ddx, ddy;
	for (int i = 0;i < 4;i++) {
		ddx = x + dx[i];
		ddy = y + dy[i];
		if (ddx > m || ddx<1 || ddy>n || ddy < 1)
			continue;
		if (arr[ddx][ddy] > 0 && book[ddx][ddy] == 0) {
			book[ddx][ddy] = 1;
			sum++;
			dfs(ddx, ddy);
		}
	}
}
int main() {
	cin >> m >> n >> x >> y;
	for (int i = 1;i <= m;i++)
		for (int j = 1;j <= n;j++)
			cin >> arr[i][j];
	book[x][y] = 1;
	dfs(x, y);
	cout << sum;
	return 0;
}

//bfs求岛屿面积
typedef pair<int, int> PII;
const int N = 110;
int arr[N][N], book[N][N] = { 0 },m,n,x,y,ans=1;

int main() {
	queue<PII>q;
	int dx[4] = { 1,0,-1,0 };
	int dy[4] = { 0,1,0,-1 };
	int ddx, ddy;
	cin >> m >> n>>x>>y;
	for (int i = 1;i <= m;i++)
		for (int j = 1;j <= n;j++)
			cin >> arr[i][j];
	book[x][y] = 1;
	q.push({ x,y });
	while (!q.empty()) {
		auto tmp = q.front();
		for (int i = 0;i < 4;i++) {
			ddx = tmp.first + dx[i];
			ddy = tmp.second + dy[i];
			if (ddx > m || ddx<1 || ddy>n || ddy < 1)
				continue;
			if (arr[ddx][ddy] > 0 && book[ddx][ddy] == 0) {
				book[ddx][ddy] = 1;
				q.push({ ddx,ddy });
				ans++;
			}
		}
		q.pop();
	}
	cout << ans;
	return 0;
}

//dfs求最短路(bfs也可以)
const int N = 110;
int Min = 99999, arr[N][N], m, n, book[N][N] = { 0 },p,q;
void dfs(int x,int y , int step) {
	int ddx, ddy;
	int dx[4] = { 1,0,-1,0 };
	int dy[4] = { 0,1,0,-1 };
	if (x == p && y == q) {
		if (step < Min) {
			Min = step;
		}
		return;
	}
	for (int i = 0;i < 4;i++) {
		ddx = x + dx[i];
		ddy = y + dy[i];
		if (ddx > m || ddx<1 || ddy>n ||ddy < 1)
			continue;
		if (arr[ddx][ddy] == 0 && book[ddx][ddy] == 0) {
			book[ddx][ddy] = 1;
			dfs(ddx, ddy, step + 1);
			book[ddx][ddy] = 0;
		}
	}
}
int main() {
	cin >> m >> n;
	for (int i = 1;i <= m;i++) {
		for (int j = 1;j <= n;j++) {
			cin >> arr[i][j];
		}
	}
	cin >> p >> q;
	book[1][1] = 1;
	dfs(1,1,0);
	cout << Min;
	return 0;
}

点击全文阅读


本文链接:http://zhangshiyu.com/post/41103.html

算法  最短  拓扑  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1