计蒜客T1651 - 道路重建 - Dijkstra/Floyd变形
题意
给出n,表示有n个城市
然后给出m,接下去给出m条道路,每条路给出x、y、z,表示x到y是一条双向边,权值为z
接下去给出r,然后给出r条被摧毁的道路,每条路给出x、y,表示x到y这条双向边被摧毁了
最后给出s和t,表示起点城市和终点城市
问我们现在要从s到t,最少需要修建路的长度是多少。
思路
一拿到这道题,我就觉得用Dijkstra,(当然也可以用Floyd、SPFA等啦),但是看着是模板题,但是我不知道咋写,好久没写了。
下面我用的是Dijkstra AC的,有别人写的Floyd代码也在下面了,Floyd代码短也简单,这道题的数据也很小。
但我总觉得Dijkstra是万能的,哈拉哈拉~
正确思路:我们除了开e数组去记录给出的道路,还需要开一个bad数组去记录被摧毁的道路。现在我们只要把可达的道路之间距离设为0,然后只需要去计算被e在bad中村的被摧毁的道路的最短路就行。
Dijkstra AC代码
#include<iostream>
#include<string.h>
#include<cmath>
#include<map>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long ll;
int n,m,r,s,t;
const int N=110;
int e[N][N],dis[N],bad[N][N];
bool book[N];
void dijkstra()
{
book[s]=1;
for(int i=1;i<=n;i++)
dis[i]=bad[s][i];
for(int i=2;i<=n;i++)
{
int mi=inf,k=-1;
for(int j=1;j<=n;j++)
if(!book[j]&&dis[j]<mi) mi=dis[j],k=j;
if(k==-1) break;
book[k]=1;
for(int j=1;j<=n;j++)
dis[j]=min(dis[j],dis[k]+bad[k][j]);
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
if(i!=j) e[i][j]=inf;
}
memset(bad,inf,sizeof(bad));
cin>>m;
for(int i=0;i<m;i++)
{
int x,y,z;
cin>>x>>y>>z;
if(z<e[x][y])
e[x][y]=e[y][x]=z,bad[x][y]=bad[y][x]=0;
}
cin>>r;
// memset(bad,0,sizeof(bad));
for(int i=0;i<r;i++) //被摧毁的城市
{
int x,y;
cin>>x>>y;
// e[x][y]=e[y][x]=inf;
bad[x][y]=bad[y][x]=e[x][y];
}
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=n;j++)
// cout<<i<<"**"<<j<<"**"<<bad[i][j]<<endl;
// }
cin>>s>>t;
dijkstra();
cout<<dis[t]<<endl;
return 0;
}