tx774 @ 2023-09-18 21:14:09
tr
第一份代码使用了bool operator但是WA #1 & #5
而第二份代码成功AC
第一份:
/*
2018年7月19日,某位同学在 NOI D1T1归程一题里非常熟练地使用了一个广为人知的算法求最短路。
然后呢?
100 →60;
Ag →Cu
最终,他因此没能与理想的大学达成契约。
大K 衷心祝愿大家不再重蹈覆辙。
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5;
const int INF=0x3f3f3f3f3f3f3f3f;
int n,m,s,dis[N];//dis数组表示起点到某点的最短路大小
bool vis[N];
struct Edge{
int to,w,nxt;
}e[N*2];int tot,head[N];
inline void addedge(int u,int v,int w)//链式前向星存图。
{e[++tot].to=v;e[tot].w=w;e[tot].nxt=head[u];head[u]=tot;}
struct cmp{
bool operator()(const int &x, const int &y) const{
return dis[x]>dis[y];
}//Priaority_queue 的 Compare 需要使用结构体的运算符重载完成,直接 bool cmp 是无法通过编译的。
};priority_queue<int,vector<int>,cmp> q;
void dijkstra(int o)
{
memset(dis,0x3f,sizeof(dis));//初始化
memset(vis,0,sizeof(vis));
dis[o] = 0;
q.push(o);
while(!q.empty())
{
int now=q.top();q.pop();
if(vis[now]) continue;
vis[now]=1;
for(int i=head[now];i;i=e[i].nxt)
{
int to=e[i].to;
if(dis[to]>dis[now]+e[i].w)
{
dis[to]=dis[now]+e[i].w;
q.push(to);
}
}
}
}
signed main()
{
cin>>n>>m>>s;
for(int i=1,u,v,w;i<=m;++i)
{
cin>>u>>v>>w;addedge(u,v,w);
}
dijkstra(s);
for(int i=1;i<=n;++i)
{
cout<<dis[i]<<" ";
}
return 0;
}
第二份:
/*
2018年7月19日,某位同学在 NOI D1T1归程一题里非常熟练地使用了一个广为人知的算法求最短路。
然后呢?
100 →60;
Ag →Cu
最终,他因此没能与理想的大学达成契约。
大K 衷心祝愿大家不再重蹈覆辙。
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5;
const int INF=0x3f3f3f3f3f3f3f3f;
int n,m,s,dis[N];//dis数组表示起点到某点的最短路大小
bool vis[N];
struct Edge{
int to,w,nxt;
}e[N*2];int tot,head[N];
inline void addedge(int u,int v,int w)//链式前向星存图。
{e[++tot].to=v;e[tot].w=w;e[tot].nxt=head[u];head[u]=tot;}
struct cmp{
bool operator()(const int &x, const int &y) const{
return dis[x]<dis[y];
}//Priaority_queue 的 Compare 需要使用结构体的运算符重载完成,直接 bool cmp 是无法通过编译的。
};//priority_queue<int,vector<int>,cmp> q;
void dijkstra(int o)
{
memset(dis,0x3f,sizeof(dis));//初始化
memset(vis,0,sizeof(vis));
priority_queue<pair<int,int> > q;
dis[o] = 0;
q.push({-dis[o], o});
while(!q.empty())
{
int now=q.top().second;q.pop();
if(vis[now]) continue;
vis[now]=1;
for(int i=head[now];i;i=e[i].nxt)
{
int to=e[i].to;
if(dis[to]>dis[now]+e[i].w)
{
dis[to]=dis[now]+e[i].w;
q.push({-dis[to], to});
}
}
}
}
signed main()
{
cin>>n>>m>>s;
for(int i=1,u,v,w;i<=m;++i)
{
cin>>u>>v>>w;addedge(u,v,w);
}
dijkstra(s);
for(int i=1;i<=n;++i)
{
cout<<dis[i]<<" ";
}
return 0;
}
by yukimianyan @ 2023-09-18 21:41:44
第一种写法会破坏堆性质,后面发生什么就不为人知了
by tx774 @ 2023-09-18 22:07:37
@yukimianyan Why?
by Code_星云 @ 2023-09-20 13:38:05
因为你这样写在实时比较时用了新的 dis 数组,但是你应该用之前求时的 dis,不然贪心是错的
by tx774 @ 2023-09-25 21:21:45
@Code_星云 但是难道不是每次更新dis时都会加一个node进堆吗,这样对于每个node比较时不都是最新dis的吗?
有没有样例或者图啥的啊
阿里嘎多:)
by d95a_4c1d @ 2023-11-09 17:01:32
@tx774 可能dis改变之后那个堆就不是一个合法的堆了(不满足父亲比儿子小), 堆的各种操作也会出错
by d95a_4c1d @ 2023-11-09 17:02:11
@tx774 此时这个堆是没法每次取最小的