【我们一起60天准备考研算法面试(大全)-第三十六天 36/60】【最短路】

专注 效率 记忆
预习 笔记 复习 做题

欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录)
 
文章字体风格:
红色文字表示:重难点★✔
蓝色文字表示:思路以及想法★✔
 
如果大家觉得有帮助的话,感谢大家帮忙
点赞!收藏!转发!

本博客带大家一起学习,我们不图快,只求稳扎稳打。
由于我高三是在家自学的,经验教训告诉我,学习一定要长期积累,并且复习,所以我推出此系列。
只求每天坚持40分钟,一周学5天,复习2天
也就是一周学10道题
60天后我们就可以学完81道题,相信60天后,我们一定可以有扎实的代码基础!我们每天就40分钟,和我一起坚持下去吧!
qq群:878080619

第三十六天【考研408-数据结构(笔试)】

  • 三十一、最短路
    • 1. 我想回家(北京大学考研机试题)
    • 2. 最短路径
    • 3. 最短路径

三十一、最短路

1. 我想回家(北京大学考研机试题)

【我们一起60天准备考研算法面试(大全)-第三十六天 36/60】【最短路】_第1张图片
求城市1到所属阵营城市的最短路径,记录在dist1[]中
求城市2到所属阵营城市的最短路径,记录在dist2[]中
遍历所有边,边的两端的城市i、j分别属于阵营1、2, 该边的权重为w
那么本题可以等价于求解:
min(w+dist[i]+dist[j])

#include 
#include 
#include 

using namespace std;

const int N=610,M=20010,INF=0x3f3f3f3f;
int n,m;
int h[N],e[M],w[M],ne[M],idx;
int q[N],dist1[N],dist2[N];
bool st[N];
int team[N];

void add(int a,int b,int c){
    e[idx]=b;
    w[idx]=c;
    ne[idx]=h[a];
    h[a]=idx++;
}

void spfa(int start,int dist[]){
    int hh=0,tt=1;
    q[0]=start;
    memset(dist,0x3f,sizeof dist1);
    dist[start]=0;

    while(hh!=tt){
        // 队头元素出队 
        int t=q[hh++];   
        if(hh==N) hh=0;  // 循环队列 
        st[t]=false;
        // 遍历该元素的所有邻接点 
        for(int i=h[t];i!=-1;i=ne[i]){
            int j=e[i];
            if(team[j]!=start)continue; // 如果是不同阵营的则跳过 
            if(dist[j]>dist[t]+w[i]){
                dist[j]=dist[t]+w[i];  // 更新,入队 
                if(!st[j]){
                    q[tt++]=j;
                    if(tt==N) tt=0; // 循环队列 
                    st[j]=true;
                }
            }
        }
    }
}
int main(){
    while(scanf("%d",&n),n){
        scanf("%d",&m);
        memset(h,-1,sizeof h),idx=0;
        while(m--){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c),add(b,a,c);   // 无向图,添加双向边 
        } 
        for(int i=1;i<=n;i++) scanf("%d",&team[i]);  // 输入所属的团队 
        spfa(1,dist1);
        spfa(2,dist2);
        int res=INF;
        for(int i=0;i<idx;i++){
            int a=e[i^1],b=e[i];// 方向相反的一对边 
            if(team[a]==1 && team[b]==2) // 如果该边连接的两个城市属于不同阵营,则可以更新边 
                res=min(res,dist1[a]+w[i]+dist2[b]); 
        }
        if(res==INF) puts("-1");
        else cout<<res<<endl; 
    }
    return 0;
}

2. 最短路径

【我们一起60天准备考研算法面试(大全)-第三十六天 36/60】【最短路】_第2张图片

#include 
#include 
#include 

using namespace std;

const int N = 110, MOD = 100000, INF = 0x3f3f3f3f;

int n, m;
int p[N];
int d[N][N];

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; i ++ ) p[i] = i;

    memset(d, 0x3f, sizeof d);
    for (int i = 0; i < n; i ++ ) d[i][i] = 0;

    for (int i = 0, len = 1; i < m; i ++, len = len * 2 % MOD)
    {
        int a, b;
        cin >> a >> b;
        if (find(a) != find(b))
        {
            p[find(a)] = find(b);
            d[a][b] = d[b][a] = len;
        }
    }

    for (int k = 0; k < n; k ++ )
        for (int i = 0; i < n; i ++ )
            for (int j = 0; j < n; j ++ )
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);

    for (int i = 1; i < n; i ++ )
        if (d[0][i] == INF) puts("-1");
        else cout << d[0][i] % MOD << endl;

    return 0;
}

3. 最短路径

【我们一起60天准备考研算法面试(大全)-第三十六天 36/60】【最短路】_第3张图片

#include 
#include 
#include 

using namespace std;

const int N = 55, M = N * N / 2, INF = 0x3f3f3f3f;

int n, m, Q;
int g[N][N], d[N][N];
struct Edge
{
    int a, b;
}e[M];

void floyd()
{
    memcpy(d, g, sizeof d);

    for (int k = 1; k <= n; k ++ )
        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= n; j ++ )
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}

int main()
{
    int T;
    cin >> T;
    while (T -- )
    {
        cin >> n >> m >> Q;
        memset(g, 0x3f, sizeof g);
        for (int i = 0; i < n; i ++ ) g[i][i] = 0;

        for (int i = 1; i <= m; i ++ )
        {
            int a, b, c;
            cin >> a >> b >> c;
            e[i] = {a, b};
            g[a][b] = g[b][a] = c;
        }

        floyd();
        printf("%d\n", d[1][n]);

        while (Q -- )
        {
            int t;
            cin >> t;
            int a = e[t].a, b = e[t].b;
            g[a][b] = g[b][a] = INF;
        }

        floyd();
        if (d[1][n] == INF) puts("-1");
        else cout << d[1][n] << endl;
    }

    return 0;
}

你可能感兴趣的:(考研,算法,面试)