1. 程式人生 > >HDU-1599-find the mincost route【最短路】【無向圖最小環】

HDU-1599-find the mincost route【最短路】【無向圖最小環】

find the mincost route

Time Limit: 1000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4341    Accepted Submission(s): 1742

Problem Description 杭州有N個景區,景區之間有一些雙向的路來連線,現在8600想找一條旅遊路線,這個路線從A點出發並且最後回到A點,假設經過的路線為V1,V2,....VK,V1,那麼必須滿足K>2,就是說至除了出發點以外至少要經過2個其他不同的景區,而且不能重複經過同一個景區。現在8600需要你幫他找一條這樣的路線,並且花費越少越好。

Input 第一行是2個整數N和M(N <= 100, M <= 1000),代表景區的個數和道路的條數。
接下來的M行裡,每行包括3個整數a,b,c.代表a和b之間有一條通路,並且需要花費c元(c <= 100)。
Output 對於每個測試例項,如果能找到這樣一條路線的話,輸出花費的最小值。如果找不到的話,輸出"It's impossible.".
Sample Input 3 3 1 2 1 2 3 1 1 3 1 3 3 1 2 1 1 2 3 2 3 1
Sample Output 3 It's impossible.
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF=0xfffffff;
//const int INF=0x3f3f3f3f; 這裡用這個就 WA 想不通為啥 
int n,m;
int map[110][110],dist[110][110];
void floyd()
{
	int ans=INF;
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<k;i++) // 一個環至少要 3個互不相同點,所以保證 k大於 i,i大於 j 
		{
			for(int j=i+1;j<k;j++)
			{
				ans=min(ans,map[i][k]+map[k][j]+dist[i][j]); // 得到從 i點出發再回到 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]); // 得到 i,j兩點的最短路徑
			}
		}
		//注意:求最短路徑的迴圈一定要放在求最小環的迴圈的下面,這是為了保證 dist[i][j]與 map[i][k]+map[k][j],不會重路
		//  ans = min ( ans , map[i][k] + map[k][j] + dist[i][j] ) 求最小環式子要求的就是 dist[i][j]中所有的中間點一定小於 k,所以不會重路 
	}
	if(ans==INF)	puts("It's impossible.");
	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++)
			{
				dist[i][j]=map[i][j]=(i==j?0:INF);
			}
		}
		int a,b,c;
		while(m--)
		{
			scanf("%d %d %d",&a,&b,&c);
			if(map[a][b]>c)
			{
				dist[a][b]=dist[b][a]=map[a][b]=map[b][a]=c;
			}
		}
		floyd();
	}
	return 0;
}