CCFCSPRO 20160911 第四题 交通规划 解题报告

问题描述
  G国国王来中国参观后,被中国的高速铁路深深的震撼,决定为自己的国家也建设一个高速铁路系统。
  建设高速铁路投入非常大,为了节约建设成本,G国国王决定不新建铁路,而是将已有的铁路改造成高速铁路。现在,请你为G国国王提供一个方案,将现有的一部分铁路改造成高速铁路,使得任何两个城市间都可以通过高速铁路到达,而且从所有城市乘坐高速铁路到首都的最短路程和原来一样长。请你告诉G国国王在这些条件下最少要改造多长的铁路。
输入格式
  输入的第一行包含两个整数nm,分别表示G国城市的数量和城市间铁路的数量。所有的城市由1到n编号,首都为1号。
  接下来m行,每行三个整数abc,表示城市a和城市b之间有一条长度为c的双向铁路。这条铁路不会经过ab以外的城市。
输出格式
  输出一行,表示在满足条件的情况下最少要改造的铁路长度。
样例输入
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 ≤ ab ≤ 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; }

 

 
posted @ 2018-10-30 15:23  zxza695  阅读(401)  评论(0编辑  收藏  举报

Contact with me