luogu P3905 道路重建 详解

luogu P3905 道路重建 题解

题目传送门

分析题目:

n n n个城市间有 m m m条道路连接
d d d条道路被破坏了,修复一些道路使 A A A B B B之间的连接

很明确了,一道最短路的题

再看数据范围:

n (2<n≤100)

m (n−1≤m≤ 1 2 n ( n − 1 ) ) \cfrac {1}{2} n(n−1)) 21n(n1))

i,j,k (1≤i,j≤n,i!=j,0<k≤100)

(1≤d≤m)

至于 m m m的值,题目给了我们一个算式,解一下:

m ≤ 100 ∗ ( 100 − 1 ) / 2 m≤100*(100-1)/2 m100(1001)/2

m ≤ 50 ∗ 99 m≤50*99 m5099

因为数据实在是太小,用Floyd最好(也就O( n 3 n^3 n3))

Floyd源码:

for(int k=1;k<=n;k++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(e[i][j]>e[i][k]+e[k][j])
				{
					e[i][j]=e[i][k]+e[k][j];
				}
			}
		}
	}

但是本题还不能直接套用Floyd的公式,因为它是要我们判断新建连边,所以我们可以定义一个二维数组e来存储已被炸毁的连边

其他的就和Floyd版题没啥区别了,记得还要初始化一下:

void init()
{
	for(int i=1;i<=n;i++)
	{
		for( int j = 1;j <= n;j++)
		{
			if(i==j)
			{
				e[i][j]=0;
			}
			else
			{
				e[i][j]=inf;
			}
		}
	}
	return ;
}

OK,只要套用以上所说的部分内容外加输出,就可以敲出全部代码:

#include<bits/stdc++.h>
using namespace std;
const int inf=INT_MAX/2-10;
int n;
int g[105][105],e[105][105];
int m,d;
int u,v,w,p,q,a,b;
void init()
{
	for(int i=1;i<=n;i++)
	{
		for( int j = 1;j <= n;j++)
		{
			if(i==j)
			{
				e[i][j]=0;
			}
			else
			{
				e[i][j]=inf;
			}
		}
	}
	return ;
}
int main(){
	cin >> n;
	init();
	cin >> m;
	for (int i=1 ; i <= m;i++)
	{
		cin >> u >> v >> w;
		g[u][v]=w;
		g[v][u]=w;
		e[u][v]=0;
		e[v][u]=0;
	}
	cin >> d;
	for(int i=1;i <= d ;i++)
	{
		cin >> p >> q;
		e[p][q]=g[p][q];
		e[q][p]=g[p][q];
	}
	cin >> a >> b;
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(e[i][j]>e[i][k]+e[k][j])
				{
					e[i][j]=e[i][k]+e[k][j];
				}
			}
		}
	}
	cout << e[a][b] << endl;
	return 0;
}
  • 25
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值