CCFCSPRO 20160911 第四题 交通规划 解题报告
问题描述
G国国王来中国参观后,被中国的高速铁路深深的震撼,决定为自己的国家也建设一个高速铁路系统。
建设高速铁路投入非常大,为了节约建设成本,G国国王决定不新建铁路,而是将已有的铁路改造成高速铁路。现在,请你为G国国王提供一个方案,将现有的一部分铁路改造成高速铁路,使得任何两个城市间都可以通过高速铁路到达,而且从所有城市乘坐高速铁路到首都的最短路程和原来一样长。请你告诉G国国王在这些条件下最少要改造多长的铁路。
建设高速铁路投入非常大,为了节约建设成本,G国国王决定不新建铁路,而是将已有的铁路改造成高速铁路。现在,请你为G国国王提供一个方案,将现有的一部分铁路改造成高速铁路,使得任何两个城市间都可以通过高速铁路到达,而且从所有城市乘坐高速铁路到首都的最短路程和原来一样长。请你告诉G国国王在这些条件下最少要改造多长的铁路。
输入格式
输入的第一行包含两个整数n, m,分别表示G国城市的数量和城市间铁路的数量。所有的城市由1到n编号,首都为1号。
接下来m行,每行三个整数a, b, c,表示城市a和城市b之间有一条长度为c的双向铁路。这条铁路不会经过a和b以外的城市。
接下来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
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。输入保证每个城市都可以通过铁路达到首都。
对于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。输入保证每个城市都可以通过铁路达到首都。
解题思路:
1.最短路径生成树,难的是证明。
2.先跑一遍到1点的最短路
3.考虑如何加点,使得 要改造铁路长度总和最小 ,这符合最小生成树的思想,考虑把最小生成树和最短路结合起来,但最短路优先级高。
对于每个点,考虑从哪些点更新过来,即满足dis[u]==dis[v]+edge[i].dis,取边权的min即可,即当前点加入点的集合中,选取最近的点连边,这符合prim的思想,只不过反了过来。
总的思想:对于每个点,在满足最短路的情况下,选择最近的点,加入最小生成树的集合中。
我考场上没有证明,举了几个反例,大胆猜想...
代码:#include<bits/stdc++.h>
#define ll long long #define R register using namespace std; const int N=10007; const int M=200015; int n,m,num,head[N],far[N],flag[N],ans; struct edge{ int nxt,to,dis; }e[M]; inline void add(R int u,R int v,R int w) { e[++num].nxt=head[u]; e[num].dis=w; e[num].to=v; head[u]=num; } inline void spfa() { for(R int i=1;i<=n;i++) far[i]=0x3f3f3f3f; far[1]=0; queue<int>q; flag[1]=1; q.push(1); while(!q.empty()) { R int u=q.front(); q.pop(); flag[u]=0; for(R int i=head[u];i;i=e[i].nxt) { R int v=e[i].to; if(far[v]>far[u]+e[i].dis) { far[v]=far[u]+e[i].dis; if(flag[v]==0) { q.push(v); flag[v]=1; } } } } } int main() { freopen("rail.in","r",stdin); freopen("rail.out","w",stdout); scanf("%d%d",&n,&m); for(R int i=1;i<=m;i++) { R int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } spfa(); for(R int u=2;u<=n;u++) { R int Min=0x3f3f3f3f; for(R int i=head[u];i;i=e[i].nxt) { R int v=e[i].to; if(far[u]==far[v]+e[i].dis) Min=min(Min,e[i].dis); } if(Min!=0x3f3f3f3f) ans+=Min; } printf("%d",ans);
return 0; }