您的位置:首页 > 编程语言 > C语言/C++

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

2018-09-02 21:12 169 查看
版权声明:欢迎转载!拒绝抄袭. https://blog.csdn.net/qq_36257146/article/details/82319081

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写了一遍,一遍搞定.上代码,真的巨简单!

[code]#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,你为啥给我零分!!!

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

 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: