[Code Plus#4] 最短路
題目背景
在北緯 91° ,有一個神奇的國度,叫做企鵝國。這里的企鵝也有自己發達的文明,稱為企鵝文明。因為企鵝只有黑白兩種顏色,所以他們的數學也是以二進制為基礎發展的。
比如早在?1110100111101001?年前,他們就有了異或這樣一個數學概念。如果你不知道異或是什么,請出門過墻左轉到這里。
再比如早在?10000101000010?年前,他們的大科學家 Penguin. Tu 就提出了圖和最短路徑這樣一些概念。
題目描述
企鵝國中有?NN?座城市,編號從?11?到?NN?。
對于任意的兩座城市?ii?和?jj?,企鵝們可以花費?(i~\mathrm{xor}~j) \times C(i?xor?j)×C?的時間從城市?ii?走到城市?jj?,這里?CC?為一個給定的常數。
當然除此之外還有?MM?條單向的快捷通道,第?ii?條快捷通道從第?F_iFi???? 個城市通向第?T_iTi???? 個城市,走這條通道需要消耗?V_iVi???? 的時間。
現在來自?Penguin?Kingdom?University 的企鵝豆豆正在考慮從城市?AA?前往城市?BB?最少需要多少時間?
輸入輸出格式
輸入格式:
?
從標準輸入讀入數據。
輸入第一行包含三個整數?N,M,CN,M,C?,表示企鵝國城市的個數、快捷通道的個數以及題面中提到的給定的常數CC?。
接下來的?MM?行,每行三個正整數?F_i,T_i,V_iFi?,Ti?,Vi??? (1 \leq F_i \leq N1≤Fi?≤N?,1 \leq T_i \leq N ,1\leq V_i \leq 1001≤Ti?≤N,1≤Vi?≤100?),分別表示對應通道的起點城市標號、終點城市標號和通過這條通道需要消耗的時間。
最后一行兩個正整數?A,BA,B?(1 \leq C \leq 100)(1≤C≤100)?,表示企鵝豆豆選擇的起點城市標號和終點城市標號。
?
輸出格式:
?
輸出到標準輸出。
輸出一行一個整數,表示從城市?AA?前往城市?BB?需要的最少時間。
?
輸入輸出樣例
輸入樣例#1:?4 2 1 1 3 1 2 4 4 1 4 輸出樣例#1:?
5 輸入樣例#2:?
7 2 10 1 3 1 2 4 4 3 6 輸出樣例#2:?
34
說明
樣例1解釋
直接從?11?走到?44?就好了。
樣例2解釋
先從?33?走到?22?,再從?22?通過通道到達?44?,再從?44?走到?66?。
?
活潑可愛的出題人給大家留下了下面這張圖。
Credit:?https://www.luogu.org/discuss/show/38908
?
?
? ? 如果暴力把圖建出來的話,邊的級別是O(N^2)的,肯定不行。。。暴力的局限在于沒有用到異或的特殊性
? ? 如果我們從一個點i,每次直走到變某一位的點,最后走到j,那么滿足至少存在一條 邊權和= i xor j的路徑,這個是比較顯然的。
? ? 所以我們把這個圖建出來然后再直接跑最短路就好啦。
但是要注意,要把n補到 2^i-1,因為有一些中間點會>n。
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=200005; int ci[33],n,m,d[maxn],val[maxn*37],C,S,T; int hd[maxn],to[maxn*37],ne[maxn*37],num; bool v[maxn]; struct node{int x,dis;bool operator <(const node &u)const{return dis>u.dis;} }; priority_queue<node> q;inline void add(int u,int v,int w){to[++num]=v,ne[num]=hd[u],hd[u]=num,val[num]=w; }inline void dij(){memset(d,0x3f,sizeof(d));d[S]=0,q.push((node){S,0});node x;while(!q.empty()){x=q.top(),q.pop();if(v[x.x]) continue;v[x.x]=1;for(int i=hd[x.x];i;i=ne[i]) if(d[x.x]+val[i]<d[to[i]]){d[to[i]]=d[x.x]+val[i];q.push((node){to[i],d[to[i]]});}}printf("%d\n",d[T]); }int main(){ci[0]=1;for(int i=1;i<=20;i++) ci[i]=ci[i-1]<<1;scanf("%d%d%d",&n,&m,&C);int uu,vv,ww;for(int i=1;i<=m;i++){scanf("%d%d%d",&uu,&vv,&ww);add(uu,vv,ww);}scanf("%d%d",&S,&T);int U=n;for(n=1;n<=U;n<<=1);n--;for(int L=0;ci[L]<=n;L++)for(int i=1,TO;i<=n;i++){TO=i^ci[L];if(TO) add(i,TO,ci[L]*C);}dij();return 0; }
轉載于:https://www.cnblogs.com/JYYHH/p/8728941.html
總結
以上是生活随笔為你收集整理的[Code Plus#4] 最短路的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 读书笔记5-处理器的微架构
- 下一篇: IDEA将Maven项目中src源代码下