[关闭]
@Gary-Ying 2018-09-26T09:12:58.000000Z 字数 3106 阅读 1013

Luo4366:[Code+#4]最短路 解题报告

最短路 位运算


Luogu · 传送门

Orz THU众大佬,lct(注意不是link-cut-tree,是一个大佬)


这道题很容易让人联想到 最短路,但是最短路需要先 建图

暴力建出所有边的算法显然是不可行的,因为这样会建出 条边;

那么我们要考虑能不能 减少一些边 ,使边的数量可以接受。

从哪里入手减少边的数量呢?异或或许是一个不错的切入口。

举个栗子:

假设我们要从 ,我们要花费 的费用;
但是,最短路有一个 优越的性质,我们可以把边拆开来,可以先从 ,再从 费用是一样的

这样我们对于每个点 ,只需要建 的边,之后 Dijkstra 就可以了哈。

需要注意的是 边界情况:从 经过的中间点可能超过 ,对此有 2 种处理方法:

  1. 建边和 Dijkstra 的范围调整为
  2. 建边和 Dijkstra 的范围调整为

方法 1 的代码

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<algorithm>
  6. #include<queue>
  7. using namespace std;
  8.  
  9. const int maxn = 100007;
  10. const int maxm = 2500007;
  11. int n, m, c;
  12. int edgenum, head[maxn], nxt[maxm], vet[maxm], val[maxm];
  13. inline void addedge(int u, int v, int w){
  14.     ++edgenum;
  15.     vet[edgenum] = v;
  16.     val[edgenum] = w;
  17.     nxt[edgenum] = head[u];
  18.     head[u] = edgenum;
  19. }
  20.  
  21. inline int read(){
  22.     int f = 1, val = 0; char ch = getchar();
  23.     while ((ch < '0' || ch > '9') && (ch != '-')) ch = getchar();
  24.     if (ch == '-') f = -1, ch = getchar();
  25.     while (ch >= '0' && ch <= '9') val = (val << 3) + (val << 1) + ch - '0', ch = getchar();
  26.     return val * f;
  27. }
  28.  
  29. int dist[maxn];
  30. bool vis[maxn];
  31. #define pii pair<int, int>
  32. priority_queue< pii, vector< pii >, greater< pii > > Qmin;
  33. const int INF = 1000000007;
  34. inline void Dijkstra(int s){
  35.     for (int i = 0; i <= n; ++i){
  36.         vis[i] = false;
  37.         dist[i] = INF;
  38.     }
  39.     dist[s] = 0; Qmin.push( make_pair(0, s) );
  40.     for (int i = 0; i <= n; ++i){
  41.         while (!Qmin.empty() && vis[Qmin.top().second]) Qmin.pop();
  42.         if (Qmin.empty()) break;
  43.         int u = Qmin.top().second; Qmin.pop();
  44.         vis[u] = true;
  45.         for (int e = head[u]; e; e = nxt[e]){
  46.             int v = vet[e], cost = val[e];
  47.             if (dist[v] > dist[u] + cost){
  48.                 dist[v] = dist[u] + cost;
  49.                 Qmin.push( make_pair(dist[v], v) );
  50.             }
  51.         }
  52.     }
  53. }
  54.  
  55. int main(){
  56.     n = read(); m = read(); c = read();
  57.     for (int i = 1; i <= m; ++i){
  58.         int u = read(), v = read(), w = read();
  59.         addedge(u, v, w);
  60.     }
  61.      
  62.     for (int i = 0; i <= n; ++i){
  63.         for (int j = 0; j < 20; ++j){
  64.             int to = i ^ (1 << j);
  65.             if (to <= n) addedge(i, to, c * (1 << j));
  66.         }
  67.     }
  68.      
  69.     int A = read(), B = read();
  70.     Dijkstra(A);
  71.      
  72.     printf("%d\n", dist[B]);
  73.     return 0;
  74. }

方法 2 的代码

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<algorithm>
  6. #include<queue>
  7. #define pii pair<int,int>
  8. using namespace std;
  9. const int maxn = 200007;
  10. const int maxm = 3000007;
  11. int n, m, C, lgn, A, B;
  12. int edgenum, hea[maxn], vet[maxm], nxt[maxm], val[maxm];
  13. inline void addedge(int u, int v, int cost){
  14. ++edgenum;
  15. vet[edgenum] = v;
  16. val[edgenum] = cost;
  17. nxt[edgenum] = hea[u];
  18. hea[u] = edgenum;
  19. //printf("%d -> %d (%d)\n", u, v, cost);
  20. }
  21. inline int read(){
  22. int f=1, val=0; char ch=getchar();
  23. while ((ch<'0'||ch>'9')&&(ch!='-')) ch=getchar();
  24. if (ch=='-') f=-1,ch=getchar();
  25. while (ch>='0'&&ch<='9') val=(val<<3)+(val<<1)+ch-'0',ch=getchar();
  26. return val*f;
  27. }
  28. int dist[maxn];
  29. bool vis[maxn];
  30. priority_queue<pii, vector< pii >, greater< pii > > Qmin;
  31. inline void Dijkstra(int s){
  32. for (int i = 1; i <= n; ++i){
  33. vis[i] = false;
  34. dist[i] = 1000000000;
  35. }
  36. dist[s] = 0; Qmin.push(make_pair(0, s));
  37. for (int i = 1; i <= n; ++i){
  38. while (!Qmin.empty() && vis[Qmin.top().second]) Qmin.pop();
  39. if (Qmin.empty()) break;
  40. int u = Qmin.top().second; Qmin.pop();
  41. vis[u] = true;
  42. for (int e = hea[u]; e; e = nxt[e]){
  43. int v = vet[e], cost = val[e];
  44. if (dist[v] > dist[u] + cost) dist[v] = dist[u] + cost, Qmin.push(make_pair(dist[v], v));
  45. }
  46. }
  47. }
  48. int main(){
  49. n = read(); m = read(); C = read();
  50. for (int i = 1; i <= m; ++i){
  51. int u = read(), v = read(), cost = read();
  52. addedge(u, v, cost);
  53. }
  54. lgn = floor(log2(n)) + 1;
  55. n = (1 << lgn) - 1;
  56. for (int i = 1; i <= n; ++i){
  57. for (int j = 0; j < lgn; ++j)
  58. addedge(i, i ^ (1 << j), (1 << j) * C);
  59. }
  60. A = read(); B = read();
  61. Dijkstra(A);
  62. printf("%d\n", dist[B]);
  63. return 0;
  64. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注