专栏文章
题解:P14307 【MX-J27-T4】点灯
P14307题解参与者 4已保存评论 4
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 4 条
- 当前快照
- 1 份
- 快照标识符
- @minhtjgv
- 此快照首次捕获于
- 2025/12/02 02:39 3 个月前
- 此快照最后确认于
- 2025/12/02 02:39 3 个月前
一些闲话
题意转化
赛时看到这道题感觉长得很像 加工零件,所以往这方面想了一下。
由于最开始可以理解为有无限多的人,所以肯定是联通且能走的所有节点全都有无限的人走过去。
而在下一天,又有无限的人回到这一个点。
具体来说,如果第 天能走到 节点,那么 天一定能走到 节点,因为只要走到了 节点,上一步走过来的那一条边可以支持它拖 的时间。
然后就很明显跑一个奇偶步数最短路。
这个时候 节点就会出现问题,因为只有 节点没有上一步。
但是题目中有这么一句话:特别地,如果这样的道路不存在,则这位点灯人会失望地离开这个国家。
那就简单了,如果开始时 节点没有任何一个点可以移动,答案就是
由于最开始可以理解为有无限多的人,所以肯定是联通且能走的所有节点全都有无限的人走过去。
而在下一天,又有无限的人回到这一个点。
具体来说,如果第 天能走到 节点,那么 天一定能走到 节点,因为只要走到了 节点,上一步走过来的那一条边可以支持它拖 的时间。
然后就很明显跑一个奇偶步数最短路。
这个时候 节点就会出现问题,因为只有 节点没有上一步。
但是题目中有这么一句话:特别地,如果这样的道路不存在,则这位点灯人会失望地离开这个国家。
那就简单了,如果开始时 节点没有任何一个点可以移动,答案就是
-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 条评论,欢迎与作者交流。
正在加载评论...