ccf交通规划巨简单(c++100)

G国国王来中国参观后,被中国的高速铁路深深的震撼,决定为自己的国家也建设一个高速铁路系统。
  建设高速铁路投入非常大,为了节约建设成本,G国国王决定不新建铁路,而是将已有的铁路改造成高速铁路。现在,请你为G国国王提供一个方案,将现有的一部分铁路改造成高速铁路,使得任何两个城市间都可以通过高速铁路到达,而且从所有城市乘坐高速铁路到首都的最短路程和原来一样长。请你告诉G国国王在这些条件下最少要改造多长的铁路。

输入格式

  输入的第一行包含两个整数n, m,分别表示G国城市的数量和城市间铁路的数量。所有的城市由1到n编号,首都为1号。
  接下来m行,每行三个整数a, b, c,表示城市a和城市b之间有一条长度为c的双向铁路。这条铁路不会经过a和b以外的城市。

输出格式

  输出一行,表示在满足条件的情况下最少要改造的铁路长度。

样例输入

4 5
1 2 4
1 3 5
2 3 2
2 4 3
3 4 2

样例输出

11

评测用例规模与约定

  对于20%的评测用例,1 ≤ n ≤ 10,1 ≤ m ≤ 50;
  对于50%的评测用例,1 ≤ n ≤ 100,1 ≤ m ≤ 5000;
  对于80%的评测用例,1 ≤ n ≤ 1000,1 ≤ m ≤ 50000;
  对于100%的评测用例,1 ≤ n ≤ 10000,1 ≤ m ≤ 100000,1 ≤ a, b ≤ n,1 ≤ c ≤ 1000。输入保证每个城市都可以通过铁路达到首都。

 

 


天杀的...楼主要疯啦!!!!

之前用dijsktral算法妄想解决这个问题,思路也是对的,因为有4->3->1和4->2->1两条路可以走,两条路的长度都一样,但是导致了整个布局的总长度不一样.(⊙o⊙)…为什么呢?楼主想到了其实4点也是建立在其他点的最短路径上的,所以当有路的总长度相同时,我肯定是在(3,4)和(2,4)之间选最短的,既然其他的路是已经确定好了的.

然而!!

我的老天鹅!!案例也太简单了,虽然运行成功,但是却得了0

悲剧,我以为是我思路不对.但是在网上看到有很多大神用优先队列也是这个思路.

嗯!我想的没错!

于是楼主用spfa写了一遍,一遍搞定.上代码,真的巨简单!

#include <iostream>
#include <vector>
#include <string.h>
#include <cmath>
#include <queue>
#define maxn 10001
#define inf 0x3f3f3f3f
using namespace std;
int n;
struct Node{
    int des;
    int far;
    Node(int a,int b){
        des = a;
        far = b;
    }
};
vector<Node>Subway[maxn];
int visited[maxn];
int dis[maxn];//距离
int pre[maxn];//记录每个点的最短前驱路径长度

void spfa(int v)
{
    queue<int>q;
    q.push(v);
    dis[v] = 0;
    visited[v] = 1;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        visited[u] = 0;
        for(int i = 0;i<Subway[u].size();i++)
        {
            int w = Subway[u][i].des;
            /**if(u == 4&&w == 3)
            {
                cout<<"dis[3]:"<<dis[3]<<" dis[4]"<<" "<<dis[4]<<endl;
            }**/
            int flag  =0;
            if(dis[w]>(dis[u]+Subway[u][i].far) )
            {
                dis[w] =  dis[u]+Subway[u][i].far;
                pre[w] = Subway[u][i].far;
                flag = 1;
            }
            if(dis[w]== dis[u]+Subway[u][i].far)//w = 4,u = 3
            {
                flag = 1;
                pre[w] = min(pre[w],Subway[u][i].far);
            }
            if(flag)
            {
                //改了之后
                if(!visited[w])
                {
                    visited[w] = 1;
                    q.push(w);
                }
            }
        }


    }
}



int main()
{
    int m;
    cin>>n>>m;
    int a,b,c;
    for(int i = 0;i<m;i++)
    {
        cin>>a>>b>>c;
        Subway[a].push_back(Node(b,c));
        Subway[b].push_back(Node(a,c));
    }
    memset(visited,0,sizeof(visited));
    memset(dis,inf,sizeof(dis));
    memset(pre,inf,sizeof(pre));
    //cout<<"visited[]"<<visited[0];
    spfa(1);
    int ans = 0;
    pre[1] = 0;
    for(int i  = 1;i<=n;i++)
    {
        ans+=pre[i];
    }
    cout<<ans<<endl;
    return 0;
}

里面的很傻的注释可以不用理啦,思路其实很清晰,还有这里有个坑是你如何记录路的长度?

楼主傻的时候,想着每个节点设一个flag,然后遍历看看谁是最短路径的....傻到爆....,但是其实每个点的前驱只有一个.

为什么只有一个?首先它会保证A的前驱到A的距离是所有可选的前驱中最短的,比如(3,4)就是最短的,其次,楼主想过假设有两条路都到4,而且最短路径长一样,甚至连前驱到它的距离都一样.

但是!!

1.第二条路径的发出点是1,既然是1->4,不就是这条嘛,其他路根本不用考虑

2.第二条路径的发出点是5(假设),1->3->4    1->5->4,而且路的长度都一样.但注意!,这里形成了一个回路,回路是不必要的,因为题目要求是任意两个城市都相连,其实就是树,而且总的长度越小越好,既然树满足要求,咱们再破一个圈总长度还更小呢...所以没有第二条路,保证了只有一个前驱

 

看完了楼主破洞百出的证明,来看看楼主的笑话

楼主一眼扫到只有一个前驱后,用一个数组来记录每个点的前驱长度,顺利一百~

 

然后愚蠢的楼主用dijsktral来重写,额滴神呀!!一晚上了都!运行11,你为啥给我零分!!!

虽然有大神用优先队列写出来了,但是私以为不用也能写出来,因为思想都是一样的,谁来告诉楼主怎么回事~

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值