博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

[Codeplus 4月赛]最短路

题意:理论上是给定一张完全图,有边权,在给一些单向边求最短路。

思路:

我充分体会到了我图论的菜。

理论上建图肯定是不能\(n^2\)的,考虑如何优化呢?

将边权异或值二进制替换,最后一遍最短路就行,记得把\(n\)开到\(2^k\)

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define mp make_pair
#define pa pair<long long,int> 
using namespace std;
const int maxn = 1000010;
priority_queue<pa,vector<pa>,greater<pa> >q;
int n,m,cnt,head[maxn],s,t,c;
bool vis[maxn];
long long dis[maxn];
struct edge{
	int to,next,v;
}e[4000010];
void add(int x,int y,int v)
{
	cnt++;e[cnt].to=y;e[cnt].next=head[x];e[cnt].v=v;head[x]=cnt;
}
void dij(int s)
{
	for (int i=0;i<=n;i++) dis[i]=1e18,vis[i]=0;
	dis[s]=0;q.push(mp(0,s));
	while (!q.empty())
	{	
		int x=q.top().second;q.pop();if (vis[x]) continue;vis[x]=1;
		for (int i=head[x];i;i=e[i].next)
		{
			int y=e[i].to;
			if (dis[y]>dis[x]+e[i].v)
				dis[y]=dis[x]+e[i].v,q.push(mp(dis[y],y));
		}
	}
}
int main()
{
	scanf("%d%d%d",&n,&m,&c);
	for (int x,y,z,i=1;i<=m;i++) scanf("%d%d%d",&x,&y,&z),add(x,y,z);
	scanf("%d%d",&s,&t);
	for (int i=0;i<=n;i++)
		for (int j=1;j<=n;j<<=1)
		{
			int y=i^j;
			if (y>n) continue;
			add(i,y,j*c);
		}
	dij(s);
	printf("%lld",dis[t]);
	return 0;
}
posted @ 2018-08-05 21:06  Allorkiya  阅读(110)  评论(0编辑  收藏  举报