基里巴斯(path)

基里巴斯(path)

题目描述

 

最近,帕特里克沉迷于世界地图上的太平洋地区。他发现了一个名字奇异的岛国:基里巴斯共和国,简称基里巴斯,是一个太平洋岛国。

其由33个岛屿组成。

“可惜它快被淹没了,该死的全球变暖”。

真悲哀。

我们这里讨论其在四维平行宇宙中的另一个国家:巴里基斯。这个国家由NN个岛屿或岛礁组成。

由于岛屿众多,政府在所有的岛屿之间均设有固定的经济航线连接。对于编号为u,v的岛屿(u,v)对,连接两岛的单向航线通行费用是(u⊕v)×K。其中,⊕表示异或(Xor)。

泛美航空公司开设了MM条往返于各岛的单向航线,每条航线均有一个固定的通行费用以期以更低的价格占有更多的用户群。

另外,泛美打算在岛礁中心建设了一个机场作为中转枢纽,这个枢纽建成后或许能大大降低泛美的航空成本。但是作为邪恶的资本主义财团,董事长还是希望调研一下收益。

于是,他打算从SS飞到城市TT。他希望得知从SS到城市TT的最小费用。

 

输入

 

输入第一行包含三个整数N,M,K,含义如题所示。

接下来MM行,每行三个整数ui,vi,wi描述一条单向航线。

最后一行两个整数S,T,表示想要调研的起点和终点。

 

输出

 

输出包含一个整数,为从SS到城市TT的最小费用。

 

样例输入

【样例1输入】
5 3 3
1 3 2
2 4 4
2 3 2
1 5
【样例2输入】
1000 1 85
829 630 1
633 492

样例输出

【样例1输出】
12
【样例2输出】
77945

提示

 

对于所有测试数据,保证:1≤K≤103,1≤wi≤105,1≤ui,vi≤n1≤K≤103,1≤wi≤105,1≤ui,vi≤n

 

详细部分分见下表:

测试点

N

M

1

 ≤105≤105 

=0

2

=1

3

=2

4

=3

5

=10

6-7

≤103≤103  

8-10

≤103≤103

11-20

≤2×105≤2×105

≤106≤106

数据不保证无重边。

 

来源

lhy

 

solution

 

对于点i

把每一位分离出来

若i的着一位为0 则lj(i,i+(1<<j))

若为1 则lj(i,i-(1<<j))

这样就能走遍所有点,边数nlogn+m

这题卡spfa。。。

很久没写dijkstra,忘光

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define maxn 200005
#define inf 1e9
using namespace std;
int n,m,K,tot,t1,t2,t3,head[maxn],S,T;
int d[maxn];
struct node{
    int v,nex;
    int w;
}e[8000005];
struct no{
    int x,v;
    bool operator <(const no &T)const{return v>T.v;}
};
priority_queue<no>q;
void lj(int t1,int t2,int t3){
    e[++tot].v=t2;e[tot].w=t3;e[tot].nex=head[t1];head[t1]=tot;
}
bool flag[maxn];
int main()
{
    cin>>n>>m>>K;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&t1,&t2,&t3);
        lj(t1,t2,t3);
    }
    cin>>S>>T;
    for(int i=1;i<=n;i++){
        for(int j=0;j<=22;j++){
            if(i&(1<<j)){
                int ne=i-(1<<j);
                if(ne<=n)lj(i,ne,(1<<j)*K);
            }
            else {
                int ne=i+(1<<j);
                if(ne<=n)lj(i,ne,(1<<j)*K);
            }
        }
    }
    for(int i=1;i<=n;i++)d[i]=inf;
    d[S]=0;no t;t.x=S,t.v=0;
    q.push(t);
    for(int i=1;i<=n;i++){
        if(q.empty())break;
        no k;
        while(flag[q.top().x]&&!q.empty())q.pop();
        if(!q.empty())k=q.top();
        else break;
        flag[k.x]=1;
        if(k.x==T)break;
        for(int i=head[k.x];i;i=e[i].nex){
            if(d[e[i].v]>d[k.x]+e[i].w&&!flag[e[i].v]){
                d[e[i].v]=d[k.x]+e[i].w;
                t.x=e[i].v,t.v=d[e[i].v];
                q.push(t);
            }
        }
    }
    cout<<d[T]<<endl;
    return 0;
}
 

 

posted @ 2018-08-14 15:26  liankewei123456  阅读(312)  评论(0编辑  收藏  举报