【图论】最小环算法

做vijos1046时想最小环想了半天,还是没想出来,到网上一搜原来是用floyd来求……

转自http://blog.csdn.net/loriex/article/details/19171415

最小环


环,,i,j,k三点,环长则为三点 两两间距,

且路不能有交点,

所以,我们想到map[i][j] + dist[i][k] + dist[j][k]

map记录最短路,dist记录直接相连的边

只要map[i][j]不过k点就算得出一个环

让最短路不过k点

想到floyd的dp方程

结果呼之欲出了吧~~我就不说了,直接上伪代码

/*由于是无向图所以计算可以少一半。。*/
dist = map;
k = 1->n;
{
i = 1->k-1;
j = i+1->k;
ans = min(ans,map[i][j] +dist[i][k] + dist[j][k] );//需注意的是i,j,k三点不能相同,所以循环终止是k-1,i-1。。。
i = 1->n;
j = 1->i;
dist[i][j] = min(dist[i][j],dist[i][k] + dist[k][j]);
}

 

vijos1046代码,最小环实用

#include 
#include 
#include 
using namespace std;
#define INF 10000000
#define MAX 101
int n,m,map[MAX][MAX];
int floyd()
{
	int mincircle = INF;
	int Dist[n+1][n+1];
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= n; j++)
	{
		Dist[i][j] = map[i][j];
	}
	for(int k = 1; k <= n; k++)
	{
		for(int i = 1; i < k; i++)
		for(int j = i+1; j < k; j++)
		{
			mincircle = min(mincircle,Dist[i][j]+map[j][k]+map[k][i]);
		}
		for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
		{
			Dist[i][j] = min(Dist[i][j],Dist[i][k] + Dist[k][j]);
		}
	}
	return mincircle;
}
void init()
{
	int b,e,l;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			map[i][j] = INF;
		}
		map[i][i] = 0;
	}
	for (int i = 1; i <= m; i++)
	{
		scanf("%d %d %d",&b,&e,&l);
		map[b][e] = map[e][b] = min(map[b][e],l);
	}
	int ans = floyd();
	if ( ans >= INF )
	{
		printf("No solution.");
	}
	else
	{
		printf("%d",ans);
	}
}
int main()
{
    freopen("in.txt","r",stdin);
	while(scanf("%d %d",&n,&m) != EOF)
	{
		init();
		printf("\n");
	}
	return 0;
}



 

你可能感兴趣的:(算法学习)