「CodePlus 2018 4 月赛」最短路

$n \leq 100000$,$m \leq 500000$的有向图,两点之间还可以以$a \ \ xor \ \ b$的代价从$a$到$b$,问$s$到$t$的最短路。

被自己蠢哭QAQ

首先两个点之间不走给定的边,最短路一定是直接$s$到$t$,因为一个二进制的差异至少要被算一次。观察$s$到$t$的过程,可以把这个过程完全等价地变成:一次只改一个二进制位,代价完全不变。因此$xor$的边只用连$nlog_2(n)$条,然后就无脑最短路了。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 #include<queue>
 5 //#include<vector>
 6 #include<algorithm>
 7 //#include<iostream>
 8 //#include<assert.h>
 9 using namespace std;
10 
11 int n,m,C,s,t;
12 #define maxn 200011
13 #define maxm 3500011
14 struct Edge{int to,next,v;}edge[maxm]; int first[maxn],le=2;
15 void in(int x,int y,int v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;}
16 
17 #define LL long long
18 LL dis[maxn];
19 struct qnode
20 {
21     LL d; int id;
22     bool operator > (const qnode &b) const {return d>b.d;}
23 };
24 priority_queue<qnode,vector<qnode>,greater<qnode> > q;
25 void dijkstra()
26 {
27     for (int i=0;i<n;i++) dis[i]=1e18;
28     dis[s]=0; q.push((qnode){0,s});
29     while (!q.empty())
30     {
31         qnode now=q.top(); q.pop();
32         if (now.d!=dis[now.id]) continue;
33         for (int i=first[now.id];i;i=edge[i].next)
34         {
35             Edge &e=edge[i];
36             if (dis[e.to]>now.d+e.v)
37             {
38                 dis[e.to]=now.d+e.v;
39                 q.push((qnode){dis[e.to],e.to});
40             }
41         }
42     }
43 }
44 
45 int main()
46 {
47     scanf("%d%d%d",&n,&m,&C);
48     {int tmp=1; while (tmp<=n) tmp<<=1; n=tmp;}
49     for (int i=0;i<n;i++)
50         for (int j=0;j<20;j++)
51         {
52             int k=i^(1<<j);
53             if (k<n) in(i,k,(1<<j)*C);
54         }
55     for (int i=1,x,y,v;i<=m;i++) scanf("%d%d%d",&x,&y,&v),in(x,y,v);
56     scanf("%d%d",&s,&t);
57     dijkstra(); printf("%lld\n",dis[t]);
58     return 0;
59 }
60 
61 /* 
62 string s;
63 string ss[10]; bool vis[10];
64 int main()
65 {
66     ss[0]="no";
67     ss[1]="no";
68     ss[2]="no";
69     ss[3]="no way";
70     ss[4]="no way";
71     ss[5]="dont even";
72     ss[6]="are you serious";
73     ss[7]="go die in a hole";
74     ss[8]="worse";
75     ss[9]="terrible";
76     bool flag=1;
77     for (int i=0;i<=9;i++)
78     {
79         cout<<i<<endl;
80         getline(cin,s);
81         bool f=0;
82         for (int j=0;j<=9;j++) if (!vis[j] && s==ss[j]) {vis[j]=1; f=1; break;}
83         if (!f) {flag=0; break;}
84     }
85     int cnt=0;
86     for (int j=0;j<=9;j++) if (vis[j]) cnt++;
87     if (cnt>=7) while (1); 
88     if (flag) puts("grumpy");
89     else puts("normal");
90 //    puts("normal");
91     return 0;
92 }
93 */ 
View Code

多出来的代码是愚人节Codeforces吸猫的错误方式。

posted @ 2018-04-02 19:42  Blue233333  阅读(516)  评论(0编辑  收藏  举报