URAL 1004. Sightseeing Trip

7 篇文章 2 订阅



求最小权值的环。有重边。需要输出路径。

一种办法是,每次去掉一条边,然后求这边连接的两点之间的最短路,加上这条边的权,就是包含这条边的最小环。执行N次。

另一种办法是,直接用Floyd来求。

Floyd第k次循环,会求出经过k这点的最短路,所以在求经过k的最短路之前 

若存在 点 i<k , j<k  ,i!=j ,且i与k之间有路,j与k之间有路  的话,这就是一个环,

权值为 i 到 k 的距离 加上  j 到 k 的距离 加 i 到 j 的最短路(这个最短路中没有经过k以及比k大的节点)

所以只要在正常的Floyd第k次循环中加入一小段判断环的代码就行了。

int MinCir;//最小环值 
vector<int> Path;//最小环路径 
int dist[maxn][maxn];//邻接矩阵 
int A[maxn][maxn]; //Floyd中用的存最短路
int path[maxn][maxn];//最短路径 
int N,M;
int main(void)
{
	while(cin>>N&&(~N)){
		//预处理 
		For(i,N){
			For(j,N){
				if(i==j) dist[i][j]=0;
				else dist[i][j]=inf;
				path[i][j]=-1;
			}
		}
		Path.clear();
		cin>>M;
		For(i,M) {
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			if(c<dist[a-1][b-1]){//去除重边,若有重边,去权值最小的 
				dist[a-1][b-1]=c;
				dist[b-1][a-1]=c;
				path[a-1][b-1]=a-1;
				path[b-1][a-1]=b-1;				
			}			
		}
		//Floyd计算最小环 
		MinCir=inf;
		For(i,N){
			For(j,N){
				A[i][j]=dist[i][j];
			}
		} 
		For(k,N){
			//求经过k的最小环
			for(int i=0;i<k;i++){
				for(int j=i+1;j<k;j++){
					int D=A[i][j]+dist[i][k]+dist[j][k];//此时A[i][j]表示的最短路没有经过k点,所以保证是环。
					if(D <MinCir){//如果找到了更小的环,保存路径。
						MinCir=D;
						Path.clear();
						int t=j;
						Path.push_back(j);
						while(path[i][t]!=i){
							Path.push_back(path[i][t]);
							t=path[i][t];
						}
						Path.push_back(i);
						Path.push_back(k);
					}
				}
			}
<span style="white-space:pre">			</span>//正常的Floyd ,求经过k的最短路。
			for(int i=0;i<N;i++){
				for(int j=0;j<N;j++){
					if(A[i][k]+A[k][j]<A[i][j]){
						A[i][j]=A[i][k]+A[k][j];
						path[i][j]=path[k][j];
					}
				}
			}
		}
		//输出
		if(MinCir>=inf)  printf("No solution.\n");
		else{
			For(i,Path.size()){
				printf("%d",Path[i]+1);
				if(i==Path.size()-1) printf("\n");
				else printf(" ");
			} 	
		}
	}
return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值