首页 > 其他分享 >Luogu P1119 灾后重建

Luogu P1119 灾后重建

时间:2023-08-20 23:14:07浏览次数:41  
标签:int Luogu element Queue read while 灾后 P1119 dis

在洛谷中查看


解法1(我想的解法,不完全正确):

很常见的套路:将询问按时间排序。时间复杂度:\(O(\;q\,(n\,logn+m)\;)\),即 \(10^9\),开 \(O2\) 才能过。

非常麻烦有没有,但我对拍的时候发现了一组数据很奇怪,待会给你们看看,我看看能不能 hack

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
#define fi first 
#define se second
const int N = 205, M = 2e4+5, Q = 5e4+5, element = 1e5+5;//注意数组大小,有点乱 
int n,m,query_num,t[N],timeline[N],nxtdate[element],ans[Q];
struct edge{
	int u,v,w;
};
vector<edge> g[element]; //每个时间都存一下 
struct Query{
	int u,v,t,id;
}q[Q];
inline int read(){
	int s=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){s=(s<<1)+(s<<3)+(c^48);c=getchar();}
	return s*f;
}
bool cmp(Query a,Query b){
	return a.t<b.t;
}
int road[N][N],dis[N];
priority_queue<P,vector<P>,greater<P> > Queue;
void dijkstra(int st){
	memset(dis,0x3f3f3f3f,sizeof(dis));
	dis[st]=0;Queue.push(P(0,st));
	while(!Queue.empty()){
		P h=Queue.top();
		Queue.pop();
		int u=h.se;
		if(dis[u]<h.fi)continue;
		for(int i=1;i<=n;i++){
			if(dis[i]>dis[u]+road[u][i]){
				dis[i]=dis[u]+road[u][i];
				Queue.push(P(dis[i],i));
			}
		}
	}
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++)t[i]=timeline[i]=read();
	for(int i=1;i<=m;i++){
		int u=read(),v=read(),w=read();
		u++,v++;
		g[max(t[u],t[v])].push_back(edge{u,v,w});
	}
	sort(timeline+1,timeline+n+1);//将时间线从小到大排序
	timeline[0]=-1;timeline[n+1]=element-1;//将timeline[0]的值设为 -1,并将timeline[n+1]的值设得比所有时间大,但也不能越界。让它有起点,有终点 
	for(int i=1;i<=n+1;i++)nxtdate[timeline[i-1]] = timeline[i];//像链表一样串起来 
	query_num=read();//变量名重了就很难受 
	for(int i=1;i<=query_num;i++)q[i]=Query{read()+1,read()+1,read(),i};
	sort(q+1,q+query_num,cmp);
	memset(road,0x3f,sizeof(road));//初始化 
	
	/*----------------------*/
	
	//下面时间复杂度是 O( q(nlogn+m) ) 的,即最多 1e9 很悬 
	int now_time=-1;
	for(int i=1;i<=query_num;i++){
		if(q[i].u==q[i].v){ans[q[i].id]=0;continue;}//在同一个点时,不管建没建好,直接输出0 
		if(t[q[i].u]>q[i].t||t[q[i].v]>q[i].t){ans[q[i].id]=-1;continue;}
		while(nxtdate[now_time]<=q[i].t){//总共只会有n次 
			now_time=nxtdate[now_time];
			for(int build=0;build<g[now_time].size();build++){
				int u=g[now_time][build].u,v=g[now_time][build].v,w=g[now_time][build].w;
				road[u][v]=road[v][u]=min(road[u][v],w);
			}
		}
		dijkstra(q[i].u);
		ans[q[i].id]=(dis[q[i].v]==0x3f3f3f3f)?-1:dis[q[i].v];
	}
	for(int i=1;i<=query_num;i++)cout<<ans[i]<<endl;
	return 0;
}

标签:int,Luogu,element,Queue,read,while,灾后,P1119,dis
From: https://www.cnblogs.com/JT-dw/p/JT-NO_9.html

相关文章

  • 【LuoGu 1363】幻象迷宫——深度优先搜索 + 读题
    幻象迷宫题目背景(喵星人LHX和WD同心协力击退了汪星人的入侵,不幸的是,汪星人撤退之前给它们制造了一片幻象迷宫。)WD:呜呜,肿么办啊……LHX:momo...我们一定能走出去的!WD:嗯,+U+U!题目描述幻象迷宫可以认为是无限大的,不过它由若干个\(N\timesM\)的矩阵重复组成。矩阵中有的地......
  • Luogu P3369 【模板】普通平衡树 01Tire树解法
    题目传送门闲话:Luogu总共105篇题解中只有4篇01Tire树解法,虽说是非正解但未免也太少了些(貌似也不少?)……总之01Tire树的效率并不低,这道题用01Tire是很轻松的。Q:这题为什么可以用01Tire树解?能否解决一个问题,无非于三个点:可行性,空间,时间。本题要求维护一个有序数集,能进行元素修改......
  • 牛的旅行 luoguP1522 多余的换行造成的影响
    牛的旅行#include<bits/stdc++.h>usingnamespacestd;intread(){intf=1,x=0;charc=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){......
  • Luogu P9510 『STA - R3』高维立方体 题解
    题目传送门没见过这玩意,写个题解记下。题目大意周知斐波那契数列定义为:\[\operatorname{fib}(n)=\left\{\begin{aligned}1&&n\le2\\\operatorname{fib}(n-1)+\operatorname{fib}(n-2)&&n>2\end{aligned}\right.\]然后定义(\(n\le0\)函数值为\(0\))\[f(n)......
  • [Luogu P8716] 回文日期 题解
    STEP1:分析题目大意:给定一个8位数的日期,请你计算该日期之后下一个回文日期和下一个ABABBABA型的回文日期各是哪一天。这一题一眼看出是P2010的升级版,所以要先考虑到超时问题,因为如果一天一天地枚举,时间复杂度会非常高,所以我们不能直接枚举。因为题目只要"回文",所以我们只......
  • LuoguP1717 钓鱼
    题面题目分析动态规划。\(\bullet\)设计状态。思考:我从哪里来?从上一个湖过来。我到哪里去?到下一个湖去\(or\)继续在这个湖钓鱼。设\(dp[pos][tim]\)为前\(pos\)个湖花费了\(tim\)分钟所能钓的最大的鱼数量。\(\bullet\)转移状态。(为了方便计算,我们将题目中的数据......
  • [刷题笔记] Luogu P1725 琪露诺
    ProblemDescription若当前在\(pos\)位置,每次可以在\([pos+l,pos+r]\)区间内任选一个点跳。每跳到一个地方就可以获得这个地方的值,最后跳到位置\(pos\geqn\)即为结束,求如何跳才能使结束的时候获得的值最大?Analysis我们发现所有操作都是在一条链上完成的,显然若再次跳到这个位......
  • 题解 LuoguP3306 [SDOI2013] 随机数生成器
    题目链接:【LuoguP3306】。前置知识OI-Wiki:快速幂,扩展欧几里得算法(exgcd),BabyStep,GiantStep算法。题意很清楚,不说。分析当\(t=x\)时答案很明显为\(1\),即在第一天就可以读到。当\(t\neqx\)时当\(a=0\)时观察一下规律:\[x_1\equivx_1\pmod{p}\]\[x_2\equivb......
  • [刷题笔记] Luogu P1280 尼克的任务
    ProblemAnalysis首先,如果一个时间只有一个任务开始,则她必须做。如果一个时间有多个任务开始,她可以选一个去做。我们发现这样的决策是取决于后面的空暇时间,而不是前面。所以在dp的时候需要从后往前搜时间(当然如果从前往后可以跑记搜)考虑转移,如果一个时间有多个任务开始,则选一个......
  • luogu P4200 千山鸟飞绝 题解 【一维数组套平衡树】
    目录题目解题思路code题目题目链接解题思路首先,此题有明显的插入、删除、查找,所以必须要使用平衡树。考虑如何使用平衡树维护每个鸟的状态。发现很不方便,因为鸟的位置改变,整个平衡树的值都要修改。考虑针对每个节点开一颗平衡树,这样就有\(3e4\times3e4\)棵树。这显然太多了......