[最短路][二進位制][Code+#4] Luogu P4366 最短路
阿新 • • 發佈:2020-07-30
運用了按位異或的玄妙性質來減小建邊量
eg. \((001)_2 \rightarrow (100)_2 = (001)_2 \rightarrow (000)_2 \rightarrow (100)_2\)
這樣我們在額外建邊時只需建 \(i \rightarrow i \ XOR \ 2^k\)
注意處理 0 號節點,因為有可能經過 0 號節點 不然會過不了樣例並 AC 本題
# include <iostream> # include <cstdio> # include <queue> # define MAXN 100005 # define MAXM 7000005 // # define MAXN 105 // # define MAXM 105 using namespace std; template<typename T> T rd(){ T fl = 1, x = 0; int ch = getchar(); for( ;!isdigit(ch); ch = getchar()){ if(ch == '-'){ fl = -1; } } for( ; isdigit(ch); ch = getchar()){ x = x * 10 + ch - '0'; } return fl * x; } // struct edge{ int u, v, next, w; }e[MAXM<<1]; int hd[MAXM<<1], cntE; void AddE(int u, int v, int w){ e[++cntE].u = u, e[cntE].v = v, e[cntE].w = w, e[cntE].next = hd[u], hd[u] = cntE; } // struct node{ int id, dis; bool operator > (const node that) const{ return this->dis > that.dis; } bool operator < (const node that) const{ return this->dis < that.dis; } }; int dis[MAXN], vis[MAXN]; void Dij(int from, int lim){ priority_queue<node, vector<node>, greater<node> >Q; for(int i = 0; i <= lim; i++){ dis[i] = 1<<25, vis[i] = 0; } // 這裡注意有可能會有從 0 出來的邊 dis[from] = 0; Q.push((node){from, dis[from]}); while(!Q.empty()){ node now = Q.top(); Q.pop(); if(vis[now.id]){ continue; } vis[now.id] = 1; for(int i = hd[now.id]; i; i = e[i].next){ if(dis[now.id] + e[i].w < dis[e[i].v]){ dis[e[i].v] = dis[now.id] + e[i].w; Q.push((node){e[i].v, dis[e[i].v]}); } } } } // int main(){ int n, m, c; n = rd<int>(), m = rd<int>(), c = rd<int>(); // // 處理加邊 for(int i = 0; i <= n; i++){ for(int j = 0, to; j <= 20; j++){ to = i ^ (1<<j); if(to <= n){ AddE(i, to, c * (1<<j)); // AddE(to, i, c * (1<<j)); } } } // 注意有可能會連到 0 位置,所以外層的遍歷要從 0 開始 // // 處理加邊 for(int i = 1, u, v, w; i <= m; i++){ u = rd<int>(), v = rd<int>(), w = rd<int>(); AddE(u, v, w); } int from, to; from = rd<int>(), to = rd<int>(); Dij(from, n); cout<<dis[to]; return 0; }