这是蒟蒻的 AC 代码,吸氧了:
蒟蒻有一个问题,上面的代码是看题解的(所以 AC,思路是节点 u 和所有 边权 为 2k 的节点连,但是为什么不是和所有 编号 为 2k 的节点连呢?
如果将所有节点包含 0 到 n,都和所有编号为 2k 的节点连,可以保证一定覆盖了所有路径,因为:
比如两个节点 a 和 b,可以保证对于任意的 2k,满足 a xor 2k + 2k xor b = a xor b 啊(?
#include <cstdio>
#include <queue>
using namespace std;
const int N = 100010;
const int INF = 1e8;
int n, m, c, s, t;
struct node { int v, w; }; vector<node> G[N];
void add()
{
scanf("%d%d%d", &n, &m, &c);
for (int i = 1, u, v, w; i <= m; i++)
scanf("%d%d%d", &u, &v, &w), G[u].push_back(node{ v,w });
scanf("%d%d", &s, &t);
for (int i = 0; i <= n; i++) /// 考虑 0 号节点
{
for (int k = 1; k <= n; k <<= 1)
{
/// i 花费 k 到 i ^ k
if ((i ^ k) > n) continue;
G[i].push_back(node{ i ^ k, k * c });
}
}
}
struct cmp {
bool operator()(node a, node b) { return a.w > b.w; }
};
priority_queue<node, vector<node>, cmp> Q;
int dis[N];
bool vis[N]; /// 是否已经确定为最短路
void dijkstra()
{
for (int i = 0; i <= n; i++) dis[i] = INF; dis[s] = 0; vis[s] = true;
for (int i = 0; i < G[s].size(); i++)
dis[G[s][i].v] = G[s][i].w, Q.push(G[s][i]);
while (!Q.empty())
{
int u = Q.top().v;
if (vis[u]) { Q.pop(); continue; }
else { dis[u] = Q.top().w; Q.pop(); vis[u] = true; }
for (int i = 0; i < G[u].size(); i++)
{
int v = G[u][i].v, w = G[u][i].w;
if (vis[v]) continue;
if (dis[v] > dis[u] + w)
dis[v] = dis[u] + w, Q.push(node{ v,dis[v] });
}
}
}
int main()
{
add();
dijkstra();
printf("%d", dis[t]);
return 0;
}
这里是未 AC 代码:
/// 只用建 u 节点和 2 ^ k 的道路即可
#include <cstdio>
#include <queue>
using namespace std;
const int N = 100010;
const int INF = 1e8;
int n, m, c, s, t;
struct node { int v, w; }; vector<node> G[N];
void add()
{
scanf("%d%d%d", &n, &m, &c);
for (int i = 1, u, v, w; i <= m; i++)
scanf("%d%d%d", &u, &v, &w), G[u].push_back(node{ v,w });
scanf("%d%d", &s, &t);
for (int i = 0; i <= n; i++)
{
for (int k = 1; k <= n; k <<= 1)
{
/// 从 i 到 k,从 k 到 i
G[i].push_back(node{ k,(i ^ k) * c });
G[k].push_back(node{ i,(i ^ k) * c });
}
}
}
struct cmp {
bool operator()(node a, node b) { return a.w > b.w; }
};
priority_queue<node, vector<node>, cmp> Q;
int dis[N];
bool vis[N]; /// 是否已经确定为最短路
void dijkstra()
{
if (s == t) return;
for (int i = 0; i <= n; i++) dis[i] = INF; dis[s] = 0; vis[s] = true;
for (int i = 0; i < G[s].size(); i++)
dis[G[s][i].v] = G[s][i].w, Q.push(G[s][i]);
while (!Q.empty())
{
int u = Q.top().v;
if (vis[u]) { Q.pop(); continue; }
else { dis[u] = Q.top().w; Q.pop(); vis[u] = true; }
for (int i = 0; i < G[u].size(); i++)
{
int v = G[u][i].v, w = G[u][i].w;
if (vis[v]) continue;
if (dis[v] > dis[u] + w)
dis[v] = dis[u] + w, Q.push(node{ v,dis[v] });
}
}
}
int main()
{
add();
dijkstra();
printf("%d", dis[t]);
return 0;
}