無向圖的最小環問題

凌曦月發表於2020-10-01

文章目錄

傳送門

思路

這道題的 n n n的資料很小, n ≤ 100 n\le100 n100,所以我們就可以用 F l o y d Floyd Floyd演算法來解決。
我們演算法模板:

for(int k=1;k<=n;k++) {
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=n;j++) {
			if(f[i][j]>f[i][k]+f[k][j])
				f[i][j]=f[i][k]+f[k][j];
		}
	}
}

每一次最外層迴圈,我們都求到了前 k k k的最短路。且這 k − 1 k-1 k1個點不包括點 k k k,並且他們的最短路徑中也不包括 k k k點。
我們就可以在這前 k − 1 k-1 k1個點中選二個點 i , j i,j i,j,因為 i − j i-j ij已經是 ( i , j ) (i,j) (i,j)間的最短路徑,且這個路徑不包含 k k k點。(注意,這兒的 i − j i-j ij可能不是 ( i , j ) (i,j) (i,j)之間的最短路,但絕對是不經過 k k k以上點的最短路。)

所以連線 i − j − k − i i-j-k-i ijki,我們就得到了一個經過 i , j , k i,j,k i,j,k的最小環。
最後每次更新 a n s ans ans的最小值即可。

程式碼

#include <bits/stdc++.h>
using namespace std;
const int INF=1e13;
int n,m;
long long a[105][105],f[105][105],ans=INF;

int main() {
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=n;j++)
			a[i][j]=f[i][j]=INF;
		a[i][i]=f[i][i]=0;
	}
	
	for(int i=1;i<=m;i++) {
		long long u,v,w;
		scanf("%lld %lld %lld",&u,&v,&w);
		a[u][v]=f[u][v]=w,a[v][u]=f[v][u]=w;
	}
	
	for(int k=1;k<=n;k++) {
		for(int i=1;i<n;i++) {
			for(int j=i+1;j<k;j++)
				if(f[i][j]+a[i][k]+a[k][j]<ans)
					ans=f[i][j]+a[i][k]+a[k][j];
		}
		
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=n;j++) {
				if(f[i][j]>f[i][k]+f[k][j])
					f[i][j]=f[i][k]+f[k][j];
			}
		}
	}
	if(ans==INF) printf("No solution.");
	else printf("%lld",ans);
	return 0;
}

相關文章