1. 程式人生 > 其它 >P4366 [Code+#4]最短路

P4366 [Code+#4]最短路

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; }