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(n−1))
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 m≤100∗(100−1)/2
m ≤ 50 ∗ 99 m≤50*99 m≤50∗99
因为数据实在是太小,用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;
}