Let life be beautiful like|

Ginger_he

园龄:3年1个月粉丝:5关注:5

洛谷P1186题解

本文同步更新于洛谷博客

题目描述

给定一张 n 个点 m 条边的带权无向图,求删除一条边后,最短路的最大值。

题解

不难发现,如果删除的边不在原图的最短路上,对结果是没有影响的。因此我们要先跑一边最短路,用 pre 数组记录下原图最短路上的每一个点。接着我们暴力枚举将每一条边删除后的最短路,取最大值即可。然后我们开开心心的交上去,发现 TLE 了。
所以我们需要优化,但是不会线段树优化怎么办?不会斐波那契堆怎么办?没关系,我们可以用 clock 函数来控制程序运行的时间,在快要超时的时候输出最优解即可。

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=1005; 
int n,m,g[maxn][maxn],dis[maxn],minn,k,ans,x,y;
bool vis[maxn],flag;
int pre[maxn];
int min(int a,int b)
{
    return a<b?a:b;
}
void dijkstra()
{
    memset(dis,0x3f,sizeof(dis));
    memset(vis,false,sizeof(vis));
    dis[1]=0;
    for(int i=1;i<n;i++)
    {
	minn=dis[0];
	for(int j=1;j<=n;j++)
	{
	    if(!vis[j]&&dis[j]<minn)
	    {
	        minn=dis[j];
		k=j;
	    }
	}
	vis[k]=true;
        for(int j=1;j<=n;j++)
	{
	    if(flag&&((k==x&&j==y)||(k==y&&j==x)))
	        continue;
	    if(!vis[j]&&dis[k]+g[k][j]<dis[j])
	    {
	        dis[j]=dis[k]+g[k][j];
		if(!flag)
		    pre[j]=k;
	    }
	}
    }
    ans=max(ans,dis[n]); 
}
int main()
{
    memset(g,0x3f,sizeof(g));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
	int a,b,v;
	scanf("%d%d%d",&a,&b,&v);
	g[a][b]=g[b][a]=min(g[a][b],v);
    }
    dijkstra();
    flag=true;//flag记录是求原图的最短路还是删边之后的最短路
    for(int i=n;i;i=pre[i])
    {
	x=i;
  	y=pre[i];
	dijkstra();
    }
    printf("%d\n",ans);
    return 0;
}

后记

这应该是我提交次数最多的一道题了……

本文作者:Ginger_he

本文链接:https://www.cnblogs.com/Gingerhe/p/15876978.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Ginger_he  阅读(56)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起