[Code+#4]最短路 (最短路)
Posted hhh1109
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Code+#4]最短路 (最短路)相关的知识,希望对你有一定的参考价值。
[Code+#4]最短路
题目背景
在北纬 91° ,有一个神奇的国度,叫做企鹅国。这里的企鹅也有自己发达的文明,称为企鹅文明。因为企鹅只有黑白两种颜色,所以他们的数学也是以二进制为基础发展的。
比如早在 1110100111101001 年前,他们就有了异或这样一个数学概念。如果你不知道异或是什么,请出门过墙左转到这里。
再比如早在 10000101000010 年前,他们的大科学家 Penguin. Tu 就提出了图和最短路径这样一些概念。
题目描述
企鹅国中有 N 座城市,编号从 1 到 N 。
对于任意的两座城市 i 和 j ,企鹅们可以花费 ((i~mathrm{xor}~j) imes C) 的时间从城市 i 走到城市 j ,这里 C 为一个给定的常数。
当然除此之外还有 (M) 条单向的快捷通道,第 (i) 条快捷通道从第 (F_i) 个城市通向第 (T_i)??? 个城市,走这条通道需要消耗 (V_i)??? 的时间。
现在来自 Penguin Kingdom University 的企鹅豆豆正在考虑从城市 A 前往城市 B 最少需要多少时间?
输入输出格式
输入格式:
从标准输入读入数据。
输入第一行包含三个整数 (N,M,C) ,表示企鹅国城市的个数、快捷通道的个数以及题面中提到的给定的常数CC。
接下来的 M 行,每行三个正整数 (F_i,T_i,V_i (1≤Fi?≤N,1 leq T_i leq N ,1leq V_i leq 100)),分别表示对应通道的起点城市标号、终点城市标号和通过这条通道需要消耗的时间。
最后一行两个正整数 A,B ((1 leq C leq 100)),表示企鹅豆豆选择的起点城市标号和终点城市标号。
输出格式:
输出到标准输出。
输出一行一个整数,表示从城市 A 前往城市 B 需要的最少时间。
输入输出样例
输入样例#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解释
直接从 1 走到 4 就好了。
样例2解释
先从 3 走到 2 ,再从 2 通过通道到达 4 ,再从 4 走到 6。
题解
一道思路非常巧妙的题目。
在这里我们要充分利用到异或的性质。
我们知道如果 A^ B ^ C ^ D =A^E时。
就直接建边A->E了。
也就是说,有些边是多余的。
那么我们怎么确保必要的边呢?
一个点到只需要连接n的每一个二进制的1就可以了。
因为所有的异或情况都可以由二进制组合出来。
那么边就是(m+log(n))的。
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N=4000001;
struct node{
int to,v,nex;
}e[N];
int num,head[N];
int n,m,c,s,t,dis[N],vis[N];
int read(){
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}
void add(int from,int to,int v){
num++;
e[num].to=to;
e[num].v=v;
e[num].nex=head[from];
head[from]=num;
}
void dijkstra(){
priority_queue<pair<int,int> >q;
memset(dis,63,sizeof(dis));dis[s]=0;
q.push(make_pair(-dis[s],s));
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;vis[u]=1;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].to;
if(dis[v]>dis[u]+e[i].v){
dis[v]=dis[u]+e[i].v;
q.push(make_pair(-dis[v],v));
}
}
}
}
int main(){
n=read();m=read();c=read();
for(int i=1;i<=m;i++){
int x=read(),y=read(),z=read();
add(x,y,z);
}
for(int i=0;i<=n;i++){
for(int j=1;j<=n;j<<=1){
if((j^i)>n)continue;
add(i,(i^j),j*c);
}
}
s=read();t=read();
dijkstra();
printf("%d
",dis[t]);
return 0;
}
以上是关于[Code+#4]最短路 (最短路)的主要内容,如果未能解决你的问题,请参考以下文章