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