zoukankan      html  css  js  c++  java
  • 题解 P6175 【无向图的最小环问题】

    这题竟然没有题解,那我就来发一篇吧。

    第一眼看到这题:最小环?什么鬼!用 SPFA 好像很麻烦欸。然后一看数据:(1leq nleq 100)。好吧这题用邻接矩阵和 floyd 就能过。

    floyd 是一种动态规划求最短路径的方法,代码极短,并且很好理解(代价就是在最短路径算法中无人能敌的 (Theta(n^3)) 的时间复杂度)。那么最短环怎么办呢,只要稍微改一下就行了!

    这是一个正常的 floyd 的核心代码(无向图):

    for(rg int k=1;k<=n;++k)  //经不经过 k。
    {
    	for(rg int i=1;i<=n;++i) //从 i 点。
    	{
    		for(rg int j=1;j<=n;++j)  //到 j 点。
    		{
    			if(f[i][j]>f[i][k]+f[k][j])  //如果经过 k 更短的话更新。 
    				f[i][j]=f[i][k]+f[k][j];
    			f[j][i]=f[i][j];  //无向图要存双向。
    		}
    	}
    }
    

    但是我们要让它为环,怎么办呢?那就在找完最短路之后再加一个循环找回路!(简单粗暴)

    我们可以用一个邻接矩阵存下这张图,如果两点不联通就为无限大(我们这里就用一个很大的数字代替无限大),所以 (f_{i,j}+a_{i,k}+a_{k,j}) 即为一个环的权值。穷举 (i,j,k) 不断更新答案就行了。

    for(rg int k=1;k<=n;++k)
    {
    	for(rg int i=1;i<k;++i)
    	{
    		for(rg int j=i+1;j<k;++j)
    		{   //这里的 a 是邻接矩阵存图。f 数组就是最短路。
    			if(ans>f[i][j]+a[i][k]+a[k][j])   //因为 a 的初始值为 1e8,就省去判断。 
    				ans=f[i][j]+a[i][k]+a[k][j];  //更新答案。 
    		}
    	}
    	for(rg int i=1;i<=n;++i)
    	{
    		for(rg 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];
    			f[j][i]=f[i][j];
    		}
    	}
    }
    

    最后提醒:要注意这是无向图,对于每次输入要存正反两次。

    完整无注释代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 110
    #define inf 1e8
    #define rg register
    int n,m,u,v,w,ans=inf;
    int a[maxn][maxn],f[maxn][maxn];
    int main()
    {
    	cin>>n>>m;
    	for(rg int i=1;i<=n;++i)
    	{	
    		for(rg int j=1;j<=n;++j)
    		{	
    			if(i!=j)
    			{	
    				a[i][j]=inf;
    				f[i][j]=inf;
    			}
    		}
    	}
    	for(rg int i=1;i<=m;++i)
    	{
    		cin>>u>>v>>w;
    		a[u][v]=w;
    		a[v][u]=w;
    		f[u][v]=w;
    		f[v][u]=w;
    	}
    	for(rg int k=1;k<=n;++k)
    	{
    		for(rg int i=1;i<k;++i)
    		{
    			for(rg int j=i+1;j<k;++j)
    			{
    				if(ans>f[i][j]+a[i][k]+a[k][j])
    					ans=f[i][j]+a[i][k]+a[k][j];
    			}
    		}
    		for(rg int i=1;i<=n;++i)
    		{
    			for(rg 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];
    				f[j][i]=f[i][j];
    			}
    		}
    	}
    	if(ans==inf)	
    		cout<<"No solution."<<endl;
    	else	
    		cout<<ans<<endl;
    	return 0;
    }
    

    其实代码很短的,只是个人码风会显得长。

  • 相关阅读:
    ViewState与Session [转]
    HTML5和HTML4的主要区别 [转]
    委托 与 Lambda
    ArcGIS 基础4-删除数据
    ArcGIS 基础3-新建数据
    ArcGIS 基础2-编辑数据
    ArcGIS 基础1-打开地图文档并浏览
    成都地铁线路图
    矢量数据库合并工具
    ArcGIS Pro试用下载步骤
  • 原文地址:https://www.cnblogs.com/win10crz/p/12859754.html
Copyright © 2011-2022 走看看