(纪中)1504. 【普及模拟】城市连接【Dijk】

67 篇文章 0 订阅

(File IO): input:city.in output:city.out
时间限制: 1000 ms 空间限制: 262144 KB 具体限制
Goto ProblemSet


题目描述
天网恢恢,疏而不漏,经过上一次的抓捕, O I OI OI总部终于获取了怪盗的特征!现在,我们需要在基德再次来之前就把他的特征送到超级大牛的手上,可惜超级大牛不在总部,所以飞过海必须尽快把资料送到大牛家里。已知 O I OI OI总部到大牛家中间有 n − 2 n-2 n2个城城市,为了尽快达到目的地,飞过海通过水晶球了解到 O I OI OI总部到大牛家的路线图,图上显示了 n n n个城之间的连接距离。
可是飞过海很忙,需要请你来帮忙编写一个程序。


输入
输入文件中的第一行为一个整数 n ( n < = 1000 ) n(n<=1000) nn<=1000
第二行至第 n + 1 n+1 n+1行,每行有 n n n个数。其中:第i+1行中表示第i个城市与其他城市之间的连接关系, 0 0 0表示不连接,其它数字表示连接的距离。

输出
输出文件中的第一行为 n n n个整数,表示所选的线路。
第二行中为一个数,表示最短距离。


样例输入
7
0 3 5 0 0 0 0
0 0 0 7 8 6 0
0 0 0 0 4 5 0
0 0 0 0 0 0 4
0 0 0 0 0 0 7
0 0 0 0 0 0 6
0 0 0 0 0 0 0

样例输出
1 2 4 7
14


数据范围限制


解题思路
Dijkstra.就行了,记录一下路径。。


代码

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
const int INF = 99999999;
struct edge {
    int next, x, w;
}a[1000010];
int vis[1010], dis[1010], head[1010], p[1010], q[1010], l, n;
void add(int u, int v, int w)
{
    a[++l].x=v;
    a[l].next=head[u];
    a[l].w=w;
    head[u] = l;
}
void dijk(int s)
{
    int k;
    for (int i = 0; i < n; i++)
    {
        dis[i] = INF;
        vis[i] = 0;
    }
    dis[s] = 0;
    vis[s] = 1;
    for (int i = 0; i < n; i++)
    {
        int minn = INF;
        for (int j = 0; j < n; j++)
            if (!vis[j] && minn > dis[j])
                minn = dis[k = j];
        vis[k] = 1;
        for (int j = head[k]; j; j = a[j].next)
        {
            int v = a[j].x;
            if (a[j].w < INF && !vis[v] && dis[v] > dis[k] + a[j].w)
            {
                p[v] = k;
                dis[v] = dis[k] + a[j].w;
            }
        }
    }
}
int main()
{
    int m, w;
    freopen("city.in","r",stdin);
    freopen("city.out","w",stdout);
    scanf("%d", &n);
        l = 0;
        memset(head, 0, sizeof(head));
        memset(p, -1, sizeof(p));
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
            {
                scanf("%d", &w);
                if (!w)
                    add(i, j, INF);
                else add(i, j, w);
            }
        dijk(0);
        int k = 0, a = n - 1;
        q[k++] = a + 1;
        while (p[a] != -1)
        {
            a = p[a];
            q[k++] = a + 1;
        }
        for (int i = n - 1; i > 0; i--)
			printf("%d ", p[i]);
        printf("%d\n%d\n", p[0], dis[n - 1]);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值