最小环算法求解(Dijkstra算法+Floyd算法)

在这里插入图片描述

方法一:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxx=105;
const int inf=0x7ffffff;
int w[maxx][maxx];
int e[maxx][maxx];
int dist[maxx];
int p[maxx];
int d[maxx][maxx];
int n,m;
int vis[maxx];
int ans;
void Dijstra(int u){
	for(int i=0;i<=n;i++){
		dist[i]=inf;
	}
	int mincost=0;
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++){
		if(u!=i){
			dist[i]=e[u][i];
			p[i]=u;
		}
	}
	vis[u]=1;
	dist[u]=0;
	for(int i=1;i<=n;i++){
		int temp=inf;
		int t=u;
		for(int j=1;j<=n;j++){
			if(!vis[j]&&dist[j]<temp){
				temp=dist[j];
				t=j;
			}
		}
		if(t==u)break;
		vis[t]=1;
		for(int j=1;j<=n;j++){
			if(e[t][j]<inf){
				if(!vis[j]&&dist[j]>dist[t]+e[t][j]){
					dist[j]=dist[t]+e[t][j];
					p[j]=t;
				}
			}
		}
	}
}
void Min_dist(){
	ans=inf;
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			if(e[k][i]!=inf){
				int temp=e[k][i];
				e[k][i]=inf;
				Dijstra(k);
				e[k][i]=temp;
				if(ans>dist[i]+temp){
					ans=dist[i]+temp;
				}
			}
		}
	}
}
int main(){
	while(cin>>n>>m){
		for(int i=0;i<=n;i++){
			dist[i]=inf;
			for(int j=0;j<=n;j++){
				e[i][j]=inf;
				d[i][j]=w[i][j]=inf;
			}
		}
		for(int i=0;i<m;i++){
			int a,b,cost;
			cin>>a>>b>>cost;
			if(w[a][b]>cost){
				w[a][b]=w[b][a]=cost;
				d[a][b]=d[b][a]=cost;
				e[a][b]=e[b][a]=cost;
			}
		}
		Min_dist();
		if(ans>=inf){
			cout<<"It's impossible."<<endl;
		}else{
			cout<<ans<<endl;
		}
	}
	return 0;
}
/*
3 3
1 2 1
2 3 1
1 3 1
3 3
1 2 1
1 2 3
2 3 1
*/

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

方法二:Floyd算法
#include<iostream>
#include<cstdio>
#define INF 0x3f3f3f
using namespace std;
int w[110][110],d[110][110];
int n,m;
void floyd()
{
    int ans=INF;
    for(int k=1;k<=n;k++){
    	//更新最小环的长度 
        for(int i=1;i<k;i++){
            for(int j=i+1;j<k;j++){
                if(ans>d[i][j]+w[i][k]+w[k][j]){
                    ans=d[i][j]+w[i][k]+w[k][j];
                }
            }
        }
        //k为环的最大编号
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(d[i][j]>d[i][k]+d[k][j]){
                    d[i][j]=d[i][k]+d[k][j];
                }
            }
        }
    }
    if(ans==INF){
        printf("It's impossible.\n");
    }
    else{
    	//输出最小环的权值 
        printf("%d\n",ans);
    }
}
int main()
{
    while(~scanf("%d %d",&n,&m)){
       for(int i=1;i<=n;i++){
	        for(int j=1;j<=n;j++){
	             d[i][j]=INF;
	             w[i][j]=INF;
	        }
       }
       int a,b,c;
	    while(m--){
             scanf("%d %d %d",&a,&b,&c);
	        if(w[a][b]>c) d[a][b]=d[b][a]=w[a][b]=w[b][a]=c;
	    }
       floyd();
    }
    return 0;
}

/*
3 3
1 2 1
2 3 1
1 3 1
3 3
1 2 1
1 2 3
2 3 1
*/

在这里插入图片描述
这是我在做题和学习中总结出来的,如果存在什么问题或错误,请指出!谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值