首页 > 其他 > 详细

Dij--P4366 [Code+#4]最短路

时间:2020-04-19 20:16:56      阅读:52      评论:0      收藏:0      [点我收藏+]

*传送

题意: 给定n个点,求从s到t的最短路径,其中有两种走法(可以混搭):一种是走给定的m有向边(ui,vi,wi);另一种可以由任意点x到任意点y,其费用是c∗(x xor y)

朴素的建法是O(n^2+m)的.然而事实上一个从x->y权值为w的边是可以被其他边取代的,我们可以把x拆成二进制,一位一位的修改最终到达y,此时经过的权值显然也是w。

举个例子:

假设我们要从 001(2)? 到 010(2)?,我们要花费 2^0 + 2^1 的费用; 但是,最短路有一个 优越的性质,我们可以把边拆开来,可以先从 001(2)? 到 000(2),再从 000(2)? 到 010(2),费用是一样的。

也就是说,对于一个点x,我们只需要让他和x*2^k连边即可,这样就优化为O(nlogn+m)了,跑一遍dij就好了。

代码:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <queue> 
 6 #include <cmath>
 7 using namespace std;
 8 int n,m,c,st,sd,x,y,val;
 9 struct node{
10     int to,next,w;
11 }ed[5000005];
12 int dis[5000005],vis[5000005],head[5000005],cnt;
13 inline void add(int u,int v,int w){
14     ed[++cnt].next=head[u];
15     ed[cnt].to=v;
16     ed[cnt].w=w;
17     head[u]=cnt;
18 }
19 inline int read(){
20     int x = 1,a = 0;
21     char ch = getchar();
22     while(ch < 0 || ch > 9){
23         if(ch == -)x = -1;
24         ch = getchar();
25     }
26     while(ch <= 9&&ch >= 0){
27         a = a * 10 + ch - 0;
28         ch = getchar();
29     }
30     return x*a;
31 }
32 priority_queue<pair<int,int> > q;
33 inline void Dij(int s){
34     q.push(make_pair(0,s));memset(vis,0,sizeof(vis));memset(dis,63,sizeof(dis));dis[s]=0;
35     while (!q.empty()){
36         int x = q.top().second;
37         q.pop();
38         if (vis[x]) continue;
39         vis[x]=1;
40         for (register int i = head[x];i;i=ed[i].next){
41             int to = ed[i].to;
42             if (dis[to]>dis[x]+ed[i].w){
43                 dis[to]=dis[x]+ed[i].w;
44                 q.push(make_pair(-dis[to],to));
45             }
46         }
47     }
48     return;
49 }
50 int main(){
51     n=read();m=read();c=read();
52     for (int i = 1;i <= m;i++){
53         x=read(),y=read(),val=read();
54         add(x,y,val);
55     }
56     int lgn = floor(log2(n)) + 1;
57     n = (1 << lgn) - 1;
58     for (register int i = 1;i <= n;i++)
59         for (register int j = 0;j < lgn;j++)
60             add(i,i^(1<<j),(1<<j)*c);
61     st=read(),sd=read();
62     Dij(st);
63     cout<<dis[sd];
64 }

 

Dij--P4366 [Code+#4]最短路

原文:https://www.cnblogs.com/very-beginning/p/12732809.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!