icpc江西:L. campus(dij最短路)

题目

在樱花盛开的季节,西湖大学吸引了大量游客,这让胥胥非常烦恼。于是,他发明了一个神奇的按钮,按下按钮后,校园里所有的游客都会以光速从最近的大门离开学校。现在,胥胥非常好奇,游客们以光速离开学校时,每时每刻所走的距离总和是多少。

具体来说,WHU 是一个无向图,有 𝑛n 个节点和 𝑚m 条边。每个节点都有 𝑎𝑖ai 名游客。在 𝑛n 个节点中, 𝑘k 个节点作为大门,每个大门的开启时间间隔为 [𝑙𝑖,𝑟𝑖][li,ri] 。问题是,从 11 到 𝑇T 的每个时刻,游客以光速离开校园的距离总和是多少?

注: 如果有游客无法离开学校,则距离之和应假设为 −1−1 。

保证给定数据的图形连通、无自循环和存在多条边。

输入

第一行包含四个整数 𝑛n ( 1≤𝑛≤1051≤n≤105 ), 𝑚m ( 1≤𝑚≤1051≤m≤105 ), 𝑘k ( 1≤𝑘≤151≤k≤15 ), 𝑇T ( 1≤𝑇≤1051≤T≤105 ).

第二行包含 𝑛n 个整数 𝑎𝑖ai ( 1≤𝑎𝑖≤1031≤ai≤103 )。( 1≤𝑎𝑖≤1031≤ai≤103 ),代表 𝑖i /-th 节点的游客数量。

接下来的每 𝑘k 行包含三个整数 𝑝𝑖pi ( 1≤𝑝𝑖≤𝑛1≤pi≤n )。( 1≤𝑝𝑖≤𝑛1≤pi≤n )、 𝑙𝑖li 、 𝑟𝑖ri ( 1≤𝑙𝑖≤𝑟𝑖≤𝑇1≤li≤ri≤T ),代表图中索引为 𝑝𝑖pi 的节点是 𝑖i /第三个大门,大门的开启时间是 [𝑙𝑖,𝑟𝑖][li,ri] 。

接下来的 𝑚m 行中每一行都包含三个整数 𝑢,𝑣,𝑤u,v,w ( 1≤𝑢,𝑣≤𝑛,1≤𝑤≤1031≤u,v≤n,1≤w≤103 ),代表 𝑢u 和 𝑣v 之间长度为 𝑤w 的路径。

输出

打印 T 行,每行包含一个整数,代表 𝑖i /-时刻的距离总和

做法

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e5+10;

int n,m,k,t,tot;
int a[N],head[N];

struct ty{
	int l,next,t;
}edge[2*N];//无向图,没乘以2报超时,血泪教训

void addedge(int x,int y,int z){
	edge[++tot].l=z;
	edge[tot].next=head[x];
	head[x]=tot;
	edge[tot].t=y;
}

struct ty2{
	int x,dis;
	bool operator < (const ty2 & a) const{
		return dis>a.dis;
	}
};

vector<int> v[N];//在时间i时开了的大门 
unordered_map<int,int> mp;//编号1~k 对应的门的编号 (直接用一个p[i]数组记录门的编号就好了)
int vis[20][N],dis[20][N];//门到各个点的最短路 
vector<pair<int,int> > g[N];//每个点i到k个门的距离  
vector<int> g1[N];每个点i到k个门的距离 (从小到大)

priority_queue<ty2> q;
void dij(int k){
	q.push({mp[k],0});
	dis[k][mp[k]]=0;
	while(q.size()){
		ty2 tmp=q.top();
		q.pop();
		if(vis[k][tmp.x]) continue;
		vis[k][tmp.x]=1;
		for(int i=head[tmp.x];i!=-1;i=edge[i].next){
			if(vis[k][edge[i].t]) continue;
			if(dis[k][tmp.x]+edge[i].l<dis[k][edge[i].t]){
				dis[k][edge[i].t]=dis[k][tmp.x]+edge[i].l;
				q.push({edge[i].t,dis[k][edge[i].t]});
			}
		}
	}
}

signed main(){
	
	memset(head,-1,sizeof(head));
	scanf("%lld%lld%lld%lld",&n,&m,&k,&t);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	
	for(int i=1;i<=k;i++){
		int p,l,r;
		scanf("%lld%lld%lld",&p,&l,&r);
		mp[i]=p;//门 
		for(int j=l;j<=r;j++){//时间 
			v[j].push_back(i);
		}
	}
	
	
	for(int i=1;i<=m;i++){
		int u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		addedge(u,v,w);
		addedge(v,u,w);
	}
	
	for(int i=1;i<=k;i++){
		for(int j=1;j<=n;j++){
			dis[i][j]=0x3f3f3f3f3f3f3f3f;
		}
	}
	
	for(int i=1;i<=k;i++)//求门到各个点的最短路
		dij(i);
	

	
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=k;j++)	{
			g[i].push_back({dis[j][i],j});
		}
		sort(g[i].begin(),g[i].end());
		for(int j=0;j<k;j++)	{
			g1[i].push_back(g[i][j].second);//每个点i到k个门的距离 (从小到大)
		}
	}
	
	int ans=0;
	
	for(int i=1;i<=t;i++){	
		
		if(v[i].size()==0) {//没有门打开,出不去 
			cout<<-1<<endl;
			continue;
		}
		
		if(v[i]==v[i-1]){//不加会超时,因为有很多情况都是只开了那几个门
			cout<<ans<<endl;
			continue;
		}
		
		ans=0;
		
		for(int j=1;j<=n;j++){
			
			for(int k=0;k<g1[j].size();k++){//门 (按距离从小到大)

				if(count(v[i].begin(),v[i].end(),g1[j][k])){//先找到肯定是最小的(最短路)
					ans+=a[j]*dis[g1[j][k]][j];
					break;
				}

			}
		}
		
		cout<<ans<<endl;
		
	}
	
}

wa的原因

一直T在样例2,结果是建边的那个数组开少了一半......还有那个特判v[i]==v[i-1]也没想到

相关推荐
luthane2 小时前
python 实现average mean平均数算法
开发语言·python·算法
静心问道2 小时前
WGAN算法
深度学习·算法·机器学习
杰九2 小时前
【算法题】46. 全排列-力扣(LeetCode)
算法·leetcode·深度优先·剪枝
manba_2 小时前
leetcode-560. 和为 K 的子数组
数据结构·算法·leetcode
liuyang-neu2 小时前
力扣 11.盛最多水的容器
算法·leetcode·职场和发展
忍界英雄2 小时前
LeetCode:2398. 预算内的最多机器人数目 双指针+单调队列,时间复杂度O(n)
算法·leetcode·机器人
Kenneth風车2 小时前
【机器学习(五)】分类和回归任务-AdaBoost算法-Sentosa_DSML社区版
人工智能·算法·低代码·机器学习·数据分析
C7211BA3 小时前
使用knn算法对iris数据集进行分类
算法·分类·数据挖掘
Tisfy3 小时前
LeetCode 2398.预算内的最多机器人数目:滑动窗口+单调队列——思路清晰的一篇题解
算法·leetcode·机器人·题解·滑动窗口
程序猿练习生3 小时前
C++速通LeetCode简单第18题-杨辉三角(全网唯一递归法)
c++·算法·leetcode