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

    题目传送门(内部题123)


    输入格式

      输入文件的第一行为四个正整数$n,m,k,d$。
      接下来$m$行,每行三个整数$u,v,w$,描述一条无向道路。
      输入文件最后一行包含$k$个整数,为$p_0,p_1,...,p_{k-1}$。


    输出格式

      一行一个整数,表示最坏情况下走出迷宫的最短路径的长度。如果最坏情况下走不出迷宫,输出$-1$。


    样例

    样例输入:

    3 4 1 1
    0 1 1
    0 1 2
    1 2 1
    1 2 2
    2

    样例输出:

    4


    数据范围与提示

      对于$50\%$的数据,满足$m=n-1$。
      对于$90\%$的数据,满足$nleqslant 1,000,mleqslant 100,000$。
      对于$100\%$的数据,满足$3leqslant nleqslant 100,000,2leqslant mleqslant 1,000,000$,道路长度均为不超过$10^9$的正整数。


    题解

    对于$m=n-1$那$50$分,就是逗你开心的,你以为是棵树,然而却又可能有重边。

    那就直接想正解吧。

    转化一下题意,就是跑一个拿第$d+1$大的$dis[v]$转移$u$的最短路。

    对于每一个点开一个堆就好了。

    再讲个故事(你们都喜欢听我讲故事为什么?)

      上午困的痛不欲生……

      (痛不欲生可海星?)

      刚考完试的我:“你们谁能$hack$一下我的算法,!@#$%^&*,大根堆,!@#$%^&*”。

      台下一片沉默……

      下午刚来到机房准备改题的我:唉,我大根堆呢?!

      

    故事讲完啦~

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

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    struct rec{int nxt,to,w;}e[2000001];
    int head[100001],cnt;
    int n,m,k,d;
    int a[100001];
    bool vis[100001],is[100001];
    long long dis[100001],ans=0x3f3f3f3f3f3f3f3f;
    priority_queue<long long>dq[100001];
    priority_queue<pair<long long,int>,vector<pair<long long,int>>,greater<pair<long long,int>>>q;
    void add(int x,int y,int w)
    {
    	e[++cnt].nxt=head[x];
    	e[cnt].to=y;
    	e[cnt].w=w;
    	head[x]=cnt;
    }
    void Dij()
    {
    	memset(dis,0x3f,sizeof(dis));
    	for(int i=1;i<=k;i++)dis[a[i]]=0;
    	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)
    		{
    			dq[e[i].to].push(dis[x]+e[i].w);
    			if(dq[e[i].to].size()>d)
    			{
    				if(dis[e[i].to]>dq[e[i].to].top())
    				{
    					dis[e[i].to]=dq[e[i].to].top();
    					q.push(make_pair(dis[e[i].to],e[i].to));
    				}
    				dq[e[i].to].pop();
    			}
    		}
    	}
    }
    int main()
    {
    	scanf("%d%d%d%d",&n,&m,&k,&d);
    	for(int i=1;i<=m;i++)
    	{
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		u++;v++;add(u,v,w);add(v,u,w);
    	}
    	for(int i=1;i<=k;i++){scanf("%d",&a[i]);a[i]++;q.push(make_pair(0,a[i]));}
    	Dij();
    	if(dis[1]==0x3f3f3f3f3f3f3f3f)puts("-1");
    	else printf("%lld",dis[1]);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    volume 方式使用 Secret【转】
    查看 Secret【转】
    用 k8s 管理机密信息【转】
    MySQL 如何使用 PV 和 PVC?【转】
    【docker问题】Client.Timeout exceeded while awaiting headers
    PV 动态供给【转】
    回收 PV【转】
    NFS PersistentVolume【转】
    PV & PVC【转】
    IO流中的常见问题
  • 原文地址:https://www.cnblogs.com/wzc521/p/11799326.html
Copyright © 2011-2022 走看看