zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:最小距离(最短路)

    题目传送门(内部题97)


    输入格式

      第一行三个整数$n,m,p$,第二行$p$个整数$x_1sim x_p$表示特殊点的编号。接下来$m$行每行三个整数$u,v,w$表示一条连接$u$和$v$,长度为$w$的边。


    输出格式

      输出一行$p$个整数,第$i$个整数表示$x_i$的答案。


    样例

    样例输入:

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

    样例输出:

    3 3 5


    数据范围与提示

      对于$10\%$的数据,$n,mleqslant 50,000,pleqslant 10$。
      对于$40\%$的数据,$n,mleqslant 50,000$。
      对于另外$5\%$的数据,$p=n$。
      对于$100\%$的数据,$1leqslant n,mleqslant 2 imes 10^5,2leqslant pleqslant n,1leqslant x_ileqslant n$,$x_i$互不相同,$1leqslant u,vleqslant n,1leqslant wleqslant 10^9$。


    题解

    把每个点都放入堆里,然后跑最短路。

    对于源点$i$,由$i$拓展的点$j$以及与$j$相邻且不由$i$拓展的点$k$,如果$i$的最优路径从$j$走到了$k$,那么走到拓展$k$的源点是最优的。

    然后枚举每一条边更新答案即可。

    时间复杂度:$Theta(mlog n)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    struct rec{int nxt,to;long long w;}e[500000];
    int head[200001],cnt=1;
    int n,m,p;
    int t[200001];
    long long dis[200001],ans[200001],f[200001];
    bool vis[200001];
    priority_queue<pair<long long,int>,vector<pair<long long,int>>,greater<pair<long long,int>>>q;
    void add(int x,int y,long long w)
    {
    	e[++cnt].nxt=head[x];
    	e[cnt].to=y;
    	e[cnt].w=w;
    	head[x]=cnt;
    }
    void Dij()
    {
    	while(q.size())
    	{
    		int x=q.top().second;
    		q.pop();
    		if(vis[x])continue;
    		vis[x]=1;
    		for(int i=head[x];i;i=e[i].nxt)
    			if(dis[e[i].to]>dis[x]+e[i].w)
    			{
    				dis[e[i].to]=dis[x]+e[i].w;
    				ans[e[i].to]=ans[x];
    				q.push(make_pair(dis[e[i].to],e[i].to));
    			}
    	}
    }
    int main()
    {
    	memset(dis,0x3f,sizeof(dis));
    	memset(f,0x3f,sizeof(f));
    	scanf("%d%d%d",&n,&m,&p);
    	for(int i=1;i<=p;i++)
    	{
    		scanf("%d",&t[i]);
    		q.push(make_pair(0,t[i]));
    		dis[t[i]]=0;ans[t[i]]=t[i];
    	}
    	for(int i=1;i<=m;i++)
    	{
    		int u,v;
    		long long w;
    		scanf("%d%d%lld",&u,&v,&w);
    		add(u,v,w);add(v,u,w);
    	}
    	Dij();
    	for(int i=2;i<=cnt;i+=2)
    	{
    		int x=ans[e[i].to];
    		int y=ans[e[i^1].to];
    		if(x==y)continue;
    		f[x]=min(f[x],dis[e[i].to]+dis[e[i^1].to]+e[i].w);
    		f[y]=min(f[y],dis[e[i].to]+dis[e[i^1].to]+e[i].w);
    	}
    	for(int i=1;i<=p;i++)printf("%lld ",f[t[i]]);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    ThinkPHP中PHPExcel的使用(包含日期格式)
    python学习一
    autocomplete 在火狐中文输入的问题
    NPM WARN 错误分析汇总
    react+reatrouter+redux学习笔记
    a++与++a的区别
    ES6箭头函数(Arrow Functions)
    document.referrer
    modem无法编译
    linux时钟浅析 转载
  • 原文地址:https://www.cnblogs.com/wzc521/p/11759289.html
Copyright © 2011-2022 走看看