计蒜客T1651

题意

给出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;
}

Floyd AC代码

https://blog.csdn.net/weixin_30344131/article/details/97984089?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_utm_term-0&spm=1001.2101.3001.4242

原文地址:https://www.cnblogs.com/OFSHK/p/14545101.html