专栏文章

题解:P14307 【MX-J27-T4】点灯

P14307题解参与者 4已保存评论 4

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
4 条
当前快照
1 份
快照标识符
@minhtjgv
此快照首次捕获于
2025/12/02 02:39
3 个月前
此快照最后确认于
2025/12/02 02:39
3 个月前
查看原文

一些闲话

各位大佬的做法都好神秘啊(应该是我太蒟蒻看不懂)。
五十分钟场切的,用的是深搜叠记忆化。
膜拜神犇 Hootime 和 TA 的 npy chenyuexiC2026

题意转化

赛时看到这道题感觉长得很像 加工零件,所以往这方面想了一下。
由于最开始可以理解为有无限多的人,所以肯定是联通且能走的所有节点全都有无限的人走过去。
而在下一天,又有无限的人回到这一个点。
具体来说,如果第 ii 天能走到 xx 节点,那么 i+2i+2 天一定能走到 xx 节点,因为只要走到了 xx 节点,上一步走过来的那一条边可以支持它拖 22 的时间。
然后就很明显跑一个奇偶步数最短路。
这个时候 11 节点就会出现问题,因为只有 11 节点没有上一步。
但是题目中有这么一句话:特别地,如果这样的道路不存在,则这位点灯人会失望地离开这个国家。
那就简单了,如果开始时 11 节点没有任何一个点可以移动,答案就是 -1

具体做法

由于我并不会 Dijkstra 的一些神秘形式,于是打了一个记忆化。
CPP
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b) 
int C,T,n,m,o,head[100005],next1[200005],to[200005],zhi[200005],cnt,aa,bb,cc,minn = 1,m1,m2,l = 1,r = 1,que[8000005][2];
#define add(a,b,c) (++cnt,to[cnt] = b,zhi[cnt] = c,next1[cnt] = head[a],head[a] = cnt)
int dist[100005][2];
void sou(){
//由于调大样例的时候递归爆炸了,于是写了一个队列,但实质上还是 DFS
	que[1][0] = 1,que[1][1] = 0;
	while(l <= r){
		int x = que[l][0],num = que[l][1];
		int qfr = num & 1;
		++l;
		for(int i = head[x];i;i = next1[i]){
			int y = to[i];
			if(num >= zhi[i]){
				int xp = (num+1) & 1;
				if(num+1 >= dist[y][xp]) continue;
				dist[y][xp] = num+1;
				++r;
				que[r][0] = y,que[r][1] = num+1;
			}
			else{
				int yqyq = (zhi[i] + 1 + ((zhi[i] - num) & 1));
				int xp = yqyq & 1;
				if(yqyq >= dist[y][xp]) continue;
				dist[y][xp] = yqyq;
				++r;
				que[r][0] = y,que[r][1] = yqyq;
			}
		}
	}
	return;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin >> C >> T;
	while(T--){
		cin >> n >> m >> o;
		for(int i = 1;i <= cnt;++i) next1[i] = to[i] = zhi[i] = 0;
		for(int i = 1;i <= n;++i) head[i] = 0,dist[i][0] = dist[i][1] = 1e16;
		cnt = 0,minn = 1e16,m1 = 0,m2 = 0,l = 1,r = 1;
		for(int i = 1;i <= m;++i){
			cin >> aa >> bb >> cc;
			--cc;//方便搜索
			add(aa,bb,cc),add(bb,aa,cc);
		}
		for(int i = head[1];i;i = next1[i]) minn = min(minn,zhi[i]);
		if(minn != 0){
			cout << -1 << endl;
			continue;
		}
		sou();
		for(int i = 1;i <= n;++i) m1 = max(m1,dist[i][0]);
		for(int i = 1;i <= n;++i) m2 = max(m2,dist[i][1]);
		int ansss = min(m1,m2);
		if(ansss >= (int)1e14) cout << -1 << endl;
		else cout << ansss * o << endl; 
	}
	return 0;
}

评论

4 条评论,欢迎与作者交流。

正在加载评论...