洛谷4366——最短路(dijkstra,思維,異或)
阿新 • • 發佈:2018-12-22
tor 分享 fontsize tdi font %d mar fin space
題目大意
給定一個n個點,m條邊的圖,每條邊有邊權,而每個點\(i\)也可以直接到達\(j\),代價是\(i\ xor\ j\),給定一個S和T,求S到T的最小代價
其中\(n\le100000,m\le100000\)
一看這個數據範圍,我們就知道顯然不能建圖~
那麽就需要一點小技巧了
就是說,一條邊可以由好幾部分的邊組合而成,而且代價還是相等的
註意 0 號結點也需要考慮(有可能兩個節點編號按位與為0 ),並把異或值控制在 n 以內(出了 n 範圍的點一定可以用 0號節點解決)
所以對於節點\(x\)我們只需要將他向 \(x\ xor \ 2^k\)連邊就可以~
因為通過這個中轉節點,他就可以到其他的能到的點,而且權值也是一樣的
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<map> #include<queue> #include<vector> #define pa pair< int , int > using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch==‘-‘) f=-1;ch=getchar();} while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();} return x*f; } const int maxn = 1e5+1e2; const int maxm = 4e6+1e2; int point[maxn],nxt[maxm],to[maxm],val[maxm]; int n,m; int vis[maxn],dis[maxn]; int cnt; int s,t; priority_queue<pa,vector<pa>,greater<pa> > q; void addedge(int x,int y,int w) { nxt[++cnt]=point[x]; to[cnt]=y; val[cnt]=w; point[x]=cnt; } int c; void dijkstra(int s) { memset(dis,127/3,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[s]=0; q.push(make_pair(0,s)); while (!q.empty()) { int x = q.top().second; q.pop(); if (vis[x]) continue; vis[x]=1; for (int i=point[x];i;i=nxt[i]) { int p = to[i]; if (dis[p]>dis[x]+val[i]) { dis[p]=dis[x]+val[i]; q.push(make_pair(dis[p],p)); } } } } int main() { scanf("%d%d%d",&n,&m,&c); for (int i=1;i<=m;++i) { int x=read(),y=read(),w=read(); addedge(x,y,w); } for (int i=0;i<=n;++i) { for (int j=1;j<=n;j<<=1) { int tmp = (i^j); if (tmp>n) continue; addedge(i,tmp,j*c); } } cin>>s>>t; dijkstra(s); cout<<dis[t]<<endl; return 0; }
洛谷4366——最短路(dijkstra,思維,異或)