[Code+#4]最短路

[Code+#4]最短路#

链接:https://www.luogu.com.cn/problem/P4366

题面:给定一个n个点,m条边的无向图,若任意点对(i,j)之间还有一条长为(ixorj)×C的边,求AB的最短路。

题解:(ixorj)×C这个式子看似很毒瘤,实际上我们可以把每一位拆开来看,若要从9走到7

((1001)2xor(111)2)×C

=(1000)2×C+(10)2×C+(100)2×C

=((1001)2xor(1)2)×C+((1)2xor(11)2)×C+((11)2xor(111)2)×C

上述等式的含义即为(1001)2>(111)2等价于(1001)2>(1)2>(11)2>(111)2

推广即得,任意(i,j)的边,都可以被拆成若干个(i,(ixor2t))的边的权值和,每一个点i(ixor2t)连边即可。

#include<iostream>
#include<queue>
using namespace std;
struct node
{
  int v,data,nxt;
};
struct reads
{
  int num,data;
  bool operator < (const reads &a)const
  {
    return data>a.data;
  }
};
reads tmp;
priority_queue<reads>q;
node edge[4000001];
int head[200001],len,dis[200001],n,m,C;
bool used[200001];
void add(int x,int y,int z)
{
  edge[++len].v=y;
  edge[len].data=z;
  edge[len].nxt=head[x];
  head[x]=len;
  return;
}
reads make_reads(int x,int y)
{
  tmp.num=x;
  tmp.data=y;
  return tmp;
}
void dijkstra(int x)
{
  q.push(make_reads(x,0));
  for (int i=0;i<=n;++i)
    dis[i]=(i!=x)*1e9;
  int top;
  while (!q.empty())
    {
      top=q.top().num;
      q.pop();
      if (used[top])
	continue;
      used[top]=1;
      for (int i=head[top];i>0;i=edge[i].nxt)
	if (dis[edge[i].v]>dis[top]+edge[i].data)
	  {
	    dis[edge[i].v]=dis[top]+edge[i].data;
	    q.push(make_reads(edge[i].v,dis[edge[i].v]));
	  }
    }
}
int main()
{
  int x,y,z,A,B;
  cin>>n>>m>>C;
  for (int i=1;i<=m;++i)
    {
      cin>>x>>y>>z;
      add(x,y,z);
    }
  for (int i=0;i<=n;++i)
    for (int k=1;k<=2*n;k*=2)
      if ((i^k)<=n)
	add(i,i^k,k*C);
  cin>>A>>B;
  dijkstra(A);
  cout<<dis[B]<<endl;
  return 0;
}
posted @   zhouhuanyi  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示
主题色彩