題目
題目概要
有一個 個點的圖,有 條有向邊直接讀入。其次,任意兩個點 之間有權值爲 的無向邊。
現求 到 的最短路。
數據範圍與約定
,邊權和 均不超過 。
思路
你以爲跟 有關?那就完全錯了。事實上,我們可以將 拆成很多步,即
其中 。所以我們直接將 和 連邊,跑最短路,結束。
代碼
#include <cstdio>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef long long int_;
int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0'||c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c&&c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
const int MaxN = 100005;
const int_ infty = (1ll<<62)-1;
struct Edge{
int to, nxt, val;
Edge(int T=0,int N=0,int V=0){
to = T, nxt = N, val = V;
}
} edge[60*MaxN];
int cntEdge, head[MaxN];
void addEdge(int a,int b,int c){
edge[cntEdge] = Edge(b,head[a],c);
head[a] = cntEdge ++;
}
struct State{
int x; int_ dis;
State(int X=0,int_ D=0):x(X),dis(D){}
bool operator < (const State &that) const {
return dis > that.dis;
}
};
priority_queue< State > pq;
int_ dis[MaxN]; int n, m, C;
void dijkstra(int from){
for(int i=0; i<=n; ++i)
dis[i] = infty;
dis[from] = 0;
pq.push(State(from,0));
while(not pq.empty()){
int x = pq.top().x;
if(dis[x] < pq.top().dis){
pq.pop(); continue;
} pq.pop();
for(int i=head[x]; ~i; i=edge[i].nxt)
if(dis[edge[i].to] > dis[x]+edge[i].val){
dis[edge[i].to] = dis[x]+edge[i].val;
pq.push(State(edge[i].to,dis[edge[i].to]));
}
}
}
int main(){
n = readint(), m = readint();
C = readint();
for(int i=1; i<=n; ++i){
head[i] = -1;
for(int j=1; j<=n; j<<=1)
if((i^j) <= n)
addEdge(i,i^j,j*C);
}
head[0] = -1;
for(int j=1; j<=n; j<<=1)
addEdge(0,j,j*C);
for(int a,b; m; --m){
a = readint(); b = readint();
addEdge(a,b,readint());
}
int A = readint();
dijkstra(A);
A = readint();
printf("%lld\n",dis[A]);
return 0;
}