P4366 [Code+#4]最短路
阿新 • • 發佈:2021-10-11
by luogu
這是一張完全圖,如果我們把所有的邊以及他的特殊邊連上肯定是要爆的。( $ n^2 + m $直接起飛
.觀察完全圖邊權的性質,是異或!比如從1走到
我們可以把每個邊按照類似二的方的方式來連邊,比如0向1,2,4,8...以此類推(注意一共有n個點,所以判一下邊界,這樣每個點就是向外連log條了
1001 ->1000
1001^1000 -> 0001
想要從0000到1111的話(因為是異或),可以過0001,0010,0100,1000
這個樣子,其他就是普通dij了
qwq
#include<bits/stdc++.h> #define int long long using namespace std;const int inf=2147483647; const int N=4e6+7; int n,m,c; int _; int head[N>>3],nxt[N<<1],to[N<<1],edge[N<<1]; void add(int x,int y,int z) { _++; nxt[_]=head[x]; head[x]=_; to[_]=y; edge[_]=z; return ; } void addedges() { for(int i=0;i<=n;i++) {for(int j=1;j<=n;j<<=1) { if((i^j)>n) continue; add(i,i^j,c*j); } } return ; } int vis[N],dis[N]; void dij(int s) { priority_queue<pair<int ,int > >q; q.push({0,s}); memset(dis,0x3f,sizeof(dis)); dis[s]=0; while(!q.empty()) { int x=q.top().second; q.pop(); if(vis[x]) continue; vis[x]=1; for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(dis[y]>dis[x]+edge[i]) { dis[y]=dis[x]+edge[i]; q.push({-dis[y],y}); } } } return ; } int st,ed; signed main() { ios::sync_with_stdio(false); cin>>n>>m>>c; addedges(); for(int i=1;i<=m;i++) { int x,y,z; cin>>x>>y>>z; add(x,y,z); } cin>>st>>ed; dij(st); cout<<dis[ed]; return 0; }