Dijkstra 死循环求助

P1948 [USACO08JAN] Telephone Lines S

把 `check()` 中第一行注释掉后虽然答案不对但死循环就没了,这是为什么
by lzy20091001 @ 2024-04-27 17:33:54


@[lzy20091001](/user/932039) 让我康康 验证码4444祭.。。2024年4月27日17:45:40
by Crab_Tang @ 2024-04-27 17:45:46


@[lzy20091001](/user/932039) 你这个马蜂好怪,就是 ``` using namespace std; ``` 加上。 _然后你都重载过了大于号为啥还要写这么复杂杂的参数,你直接``priority_queue<NODE>``好了。 _
by Crab_Tang @ 2024-04-27 17:53:08


``` memset(dis, 0x3f, 4 * (n + 1)); ``` 这样写也怪怪的。最好还是sizeof dis
by Crab_Tang @ 2024-04-27 17:54:22


@[lzy20091001](/user/932039) 呃,你直接要用operator < 然后里面是路径a<b。然后再直接写prio_que<NODE>
by Crab_Tang @ 2024-04-27 17:56:44


```cpp void dijkstra() { memset(dis, 0x3f, 4 * (n + 1)); dis[1] = 0; pq.push({1, 0}); while (!pq.empty()) { int u = pq.top().u; pq.pop(); if (u == n) return; if (vis[u]) continue; vis[u] = true; for (int i = head[u]; i != -1; i = edge[i].nxt) { int v = edge[i].to, w = t[i]; if (dis[v] > dis[u] + w) { // std::cout << u << " " << v << " " << dis[v] << " " << dis[u] << " " << w << std::endl; dis[v] = dis[u] + w; // std::cout << u << " " << v << " " << dis[v] << " " << dis[u] << " " << w << std::endl; if(!vis[v])pq.push({v, dis[v]}); } } } } ``` 也许不是因为这个原因,但已经入过堆的点显然不能再次入队
by hgckythgcfhk @ 2024-04-27 17:58:00


@[lzy20091001](/user/932039) 参考参考我这个https://www.luogu.com.cn/paste/w9glrkkw
by Crab_Tang @ 2024-04-27 17:58:27


具体的我也不会二分,也不会链式前向星,帮你调不了,但这个地方dij板子肯定打错了,可以看出你的程序中有一些不太好的习惯,比如 ```cpp std::priority_queue<Node, std::vector<Node>, std::greater<Node>> pq; ``` 这句是为了大根堆改小根堆。 ```cpp friend bool operator>(Node a, Node b) { return a.w > b.w; } ``` 重载这个运算符也是为了大根堆改小根堆,但显然你这里没改,确实避免了改两次导致错误,但是你这样和直接: ```cpp friend bool operator>(Node a, Node b) { return a.w < b.w; } priority_queue<Node> ``` 有什么区别,反正我没试过自定义类型既改运算符又改小根堆,不知道会不会出事。 还有, ```cpp memset(dis, 0x3f, 4 * (n + 1)); ``` 这个地方虽然没出事,但这不是个好习惯,类型很容易忘记改,我知道你想卡常,但可以说,到正式比赛卡常屁用没有,我学的那些高级的卡常操作到赛场上一次都没起到作用过,加一些基础的 ```register```和```inline```再关个同步就够用了,甚至大部分题这些也用不上,现在我写这些只是因为本地慢养成了随手卡常的习惯 还有,我不会二分,但我知道二分很容易死循环,你可以考虑检查一下二分,具体这样: ```cpp while (l <= r) // 二分 { int m = (l + r) / 2; cerr<<l<<' '<<r<<'\n'; if (check(m)) { ans = m; r = m + 1; } else l = m + 1; } ``` 看看是否符合预期
by hgckythgcfhk @ 2024-04-27 18:14:05


提供一种不会在二分上死循环的办法: ```cpp int ans=0;for(int i=20;~i;--i)if(chk(ans|(1<<i)))ans|=1<<i; ``` 然后,在 ```chk``` 函数第一行加上: ```cpp if(i>n)return 0; ``` 这个 $n$ 是上界,这样,你可以保证出错一定是在 ```chk``` 里面。
by hgckythgcfhk @ 2024-04-27 18:18:21


很好奇为什么链式前向星很慢而且在不背的情况下不太容易自己写出来,还有这么多人写,为什么不用 ```vector```
by hgckythgcfhk @ 2024-04-27 18:21:07


| 下一页