道路重建 (2018山东冬令营)

问题 C: 道路重建

时间限制: 1 Sec  内存限制: 128 MB
提交: 67  解决: 24
[提交][状态][讨论版]

题目描述

小L的家乡最近遭遇了一场洪水,城市变得面目全非,道路也都被冲毁了。生活还要继续,于是市政府决定重建城市中的道路。
在洪水到来前,城市中共有n个区域和m条连接这些区域的双向道路,
道路连通了所有的区域,为了方便人们的出行,只能重建这些原有的道路, 不能建新的道路。编号为s的区域是市政广场,市政府希望重建的道路能够
使得所有区域到市政广场的最短路与受灾前保持不变,同时为了节约救灾 经费,还要使得修建的所有道路的长度和尽可能小。
小L为了拯救心爱的家乡,决定站出来,成为优秀的青年理论计算机科 学家,于是马上投入到了对这个问题的研究中。你能帮帮小L吗?

输入

第一行两个整数n和m,表示区域与道路的个数。
接下来m行,每行三个正整数u,v和w,描述一条连接u和v、长为w的道路。
最后一行,一个正整数s,表示市政广场的编号。

输出

输出一个整数,表示最小长度和。

样例输入

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

样例输出

6

提示

最优方案是重建1-2,1-5,2-4,4-3的道路,此时所有区域到达区域2的最短路分别是1, 0, 4, 2, 2,道路长度和是1 + 1 + 2 + 2 = 6。
对于20%的数据,n ≤ 10, m ≤ 20;
对于另外30%的数据,边权不超过2;
对于100%的数据,1 ≤ n ≤ 105, n − 1 ≤ m ≤ 2 ∗ 105, 1 ≤ w ≤ 109

题解:spfa 外加一个pre[]数组用来存该点到上一个点的距离

代码如下:

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<map>
#define ll long long

using namespace std;
const int inf=1e9+7;

const int maxn=1e6+5;
struct Edge{
    int to,next,w;
}edge[maxn];
int head[maxn],vis[maxn],pre[maxn],cnt,n,m;
ll dis[maxn];

void add(int u,int v,int w)
{
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    edge[cnt].w=w;
    head[u]=cnt++;
}

void spfa(int s)
{
    ll ans=0;
    queue <int> q;
    for(int i=1;i<=n;i++)
        dis[i]=1e18;
    memset(vis,0,sizeof(vis));
    q.push(s);
    dis[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to,w=edge[i].w;
            if(dis[v]>=dis[u]+w)
            {
                if(dis[v]>dis[u]+w)
                {
                    ans+=w;
                    if(dis[v]!=1e18)
                        ans-=pre[v];
                    pre[v]=w;
                }
                else
                {
                    if(pre[v]>w)
                    {
                        ans+=w-pre[v];
                        pre[v]=w;
                    }
                }
                dis[v]=dis[u]+w;
                if(!vis[v])
                {
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
    }
    printf("%lld\n",ans);
}

int main()
{
    int st;
    scanf("%d%d",&n,&m);
    int u,v,w;
    for(int i=0;i<=n;i++)
        head[i]=-1;
    cnt=0;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }
    scanf("%d",&st);
    spfa(st);
    return 0;
}

原文地址:https://www.cnblogs.com/lemon-jade/p/8496731.html

时间: 2024-08-06 05:51:09

道路重建 (2018山东冬令营)的相关文章

道路重建(拓扑+贪心)

道路重建(拓扑+贪心) 一.题目 道路重建 时间限制: 1 Sec  内存限制: 128 MB 提交: 9  解决: 6 [提交][状态][讨论版] 题目描述 现在有一棵n个结点的树(结点从1到n编号),请问至少要删除几条边,才能得到一个恰好有p个结点的子树? 输入 第一行输入两个数n和p (1 <= n<= 150, 1 <= p<= n) 接下来输入n-1行,每行两个整数x y,表示x和y之间有一条边. 输出 输出答案. 样例输入 11 6 1 2 1 3 1 4 1 5 2

洛谷——P3905 道路重建

P3905 道路重建 题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B之间的交通中断,国王希望尽快的恢复两个城市之间的连接.你的任务就是修复一些道路使A与B之间的连接恢复,并要求修复的道路长度最小. 输入输出格式 输入格式: 输入文件road.in,第一行为一个整数n(2<n≤100),表示城市的个数.这些城市编号从1到n.第二行为一个整数m(n

洛谷 P3905 道路重建

P3905 道路重建 题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B之间的交通中断,国王希望尽快的恢复两个城市之间的连接.你的任务就是修复一些道路使A与B之间的连接恢复,并要求修复的道路长度最小. 输入输出格式 输入格式: 输入文件road.in,第一行为一个整数n(2<n≤100),表示城市的个数.这些城市编号从1到n.第二行为一个整数m(n

山东冬令营2018:贪心专练

T1: 数轴上有 n 个点,第 i 个点的坐标为 xi,权值为 wi.两个点 i,j 之间存在一条边当且仅当 abs(xi-xj)>=wi+wj. 你需要求出这张图的最大团的点数. (团就是两两之间有边的顶点集合) [输入格式] 输入文件clique.in 第一行一个整数 n,接下来 n 行每行两个整数 xi,wi. [输出格式] 输出文件clique.out 输出一行一个整数,表示最大团的点数. [样例输入] 4 2 3 3 1 6 1 0 2 [样例输出] 3 [数据范围] 对于 20%的数

2018 山东网络安全“十大重要活动事件”回顾

光阴荏苒,日月如梭,2018年已经悄然结束,过去一年在省委网信办.省公安厅等主管部门的领导下山东各项网络安全工作顺利开展,全省网络安全保障水平不断提高.网络安全产业加速发展.网络安全生态体系更加成熟. 山东九州信息安全研究院梳理了2018年山东省十个方面网络安全重要活动.事件与大家一起分享: (一)上合青岛峰会成功举办: 6月9日到10日,上海合作组织成员国元首理事会第十八次会议在山东省青岛市举行,国家主席×××主持会议.山东省顺利完成峰会网络安全保障工作. (二)山东省委意识形态和宣传思想工作

2018山东第九届省赛总结与反思

按比赛时的开题顺序写一下总结.反思.大概题解,以及以后的训练规划. A题大概题解: 简单讨论了一下.注意到题目要求的是变换到目的串的任意排列的最小花费,想到对两个串都按字典序排序,在B串中找到第一个大于等于A[0]的元素,之后一一对应,如果B[I]>=A[J],ans+=A[J]-B[I];否则跳过B[I],最后剩下的A中的元素与B中的元素再一一对应.一发过. 看榜,开F.F题是一个比较难想全的容斥,卡了很久,中间换题把C题一发过了. C题大概题解: 把权值最小的点与所有点相连. 之后我想E题,

「2018山东一轮集训」鸽子

窝也不知道为什么反着BFS就是对的啊QWQ #include<cstdio> #define ll long long using namespace std; const int N=2005; int n,k,m,B[2],E[2],H,T,px[N*N],py[N*N]; int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0}; bool M[N][N],v[N][N]; inline bool read(){ char ch=getchar(); while(ch!

「2018山东一轮集训」 Tree

为什么出题人这么毒瘤啊??!!一个分块还要带log的题非要出成n<=2*1e5....... 为了卡过最后两个点我做了无数常数优化,包括但不限于:把所有线段树改成 存差分的树状数组:把树剖求LCA的极小的log优化成rmq O(1)求LCA:根据测试情况手动调整siz的大小: 但就是死也卡不过去,算了算了QWQ (常规套路,先把1设成根建有根树) 这个题的主要思路就是 对节点的下标分块,设 f[i][j] 为 第i个块内所有点到点j的距离和,然后看如何快速的动态维护这个玩意.... 发现改动一条

道路重建

题面 spfa(或digstra)一遍过 1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 int p[1001][1001]; 5 int g[1001][1001]; 6 int n,m,x,y,k1,d,a,b,ans; 7 int main(){ 8 int i,k,j; 9 scanf("%d%d",&n,&m); 10 memset(g,0x3f,sizeo