【hack】关于题解中走两遍dijkstra的正确性疑问
查看原帖
【hack】关于题解中走两遍dijkstra的正确性疑问
265453
strange757楼主2022/1/25 20:35

对于题解中多篇走两遍dijkstra的方法我保持疑问,为什么显然这样是对的呢。于是我开始自己验证做法正确性。然而当我验证时造出了一组疑似能hack掉的数据。 附上代码

#include<bits/stdc++.h>
using namespace std;
int n,m,s,c,g,p,head[100100],tot,u,v,w,dis[100100];
bool vis[100100],f[100100];
struct dp1{
	int h,l;
}a[100100];
struct node{
	int next,to,w;
}edge[1000100];
struct dp{
	int w,now;
	inline bool operator <(const dp &x)const{
		return w>x.w;
	}
};
priority_queue <dp> q;
void dijkstra(){
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	q.push((dp){0,s});
	dis[s]=0;
	while(!q.empty()){
		int u=q.top().now;
		q.pop();
		if(vis[u])continue;
		vis[u]=1;
		for(int i=head[u];i;i=edge[i].next){
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].w&&!f[v]){
				dis[v]=dis[u]+edge[i].w;
				q.push((dp){dis[v],v});
			}
		}
	}
}
void add(int u,int v,int w){
	tot++;
	edge[tot].to=v;
	edge[tot].w=w;
	edge[tot].next=head[u];
	head[u]=tot;
}
int main(){
	cin>>n>>m>>s>>c>>g>>p;
	for(int i=1;i<=n;i++){
		cin>>a[i].h>>a[i].l;
	}
	for(int i=1;i<=m;i++){
		cin>>u>>v>>w;
		add(u,v,w);
		add(v,u,w);
	}
	dijkstra();
	for(int i=1;i<=n;i++){
		if(i==c)continue;
		if(dis[i]*p>a[i].l-a[i].h)f[i]=1;
	}
	dijkstra();
	if(dis[c]>g)cout<<"wtnap wa kotori no oyatsu desu!";
	else cout<<dis[c];
	return 0;
}

样例: 对于这组数据,走两遍dijkstra的结果为 而这组数据显然是无解的。 然而我发现题解中还有一种用dijkstra只走一遍的方法。这里也附上代码

#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
struct node {
	LL v , w;
	node() {}
	node(LL V , LL W) {
		v = V;
		w = W;
	}
};
struct place {
	LL h , l , _max;
}p[1000005];
LL dp[1000005] , n , r , cnt , _minsec[1000005];
vector <node> G[1000005];
bool vis[1000050];
void read(LL &x) {
	LL f = 1;x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
	while(s >= '0' && s <= '9') {x = x * 10 + s - '0'; s = getchar();}
	x *= f;
}
struct cmp1 {
	bool operator() (node &x , node &y) {
		return x.w > y.w;
	}
};
priority_queue <node , vector <node> , cmp1> q;
void dijkstra(LL s) {
	for (LL i = 1; i <= n; ++i) dp[i] = 1e16;
	dp[s] = 0;
	q.push(node(s , 0));
	while(!q.empty()) {
		node now = q.top();
		q.pop();
		LL x = now.v;
		if(vis[x]) continue;
		vis[x] = 1;
		if(now.w >= p[x]._max) continue; // 超过最大时间,不能走
		for (LL i = 0; i < G[x].size(); ++i) {
			if(dp[x] + G[x][i].w < dp[G[x][i].v]) {
				dp[G[x][i].v] = dp[x] + G[x][i].w;
				q.push(node(G[x][i].v , dp[G[x][i].v]));
			}
		}
	}
}
int main() {
	LL s , t , g , q;
	read(n);
	read(r);
	read(s);
	read(t);
	read(g);
	read(q);
	for (LL i = 1; i <= n; ++i) {
		read(p[i].h);read(p[i].l);
		if(q != 0) p[i]._max = (p[i].l - p[i].h + q - 1) / q; // 计算不能通行的时间
		else p[i]._max = 1e9; // 置为任意时刻能通行
	}
	for (LL i = 1; i <= r; ++i) {
		LL x , y , w;
		read(x);read(y);read(w);
		G[x].push_back(node(y , w));
		G[y].push_back(node(x , w));//无向图,双边
	}
	dijkstra(s);
	if(dp[t] > g) printf("wtnap wa kotori no oyatsu desu!"); 
	else printf("%lld" , dp[t]); // 输出答案
	return 0;
}

同上输入样例的结果为:

可以看见两个题解的答案是不相同的。

如果造的数据有误,请指出。

2022/1/25 20:35
加载中...