码迷,mamicode.com
首页 > 其他好文 > 详细

清北学堂-图论--二进制拆分--最短路--潜伏

时间:2019-08-15 21:25:03      阅读:93      评论:0      收藏:0      [点我收藏+]

标签:void   def   png   技术   进制   cstring   highlight   eof   mem   

技术图片

样例输入:

3
5 10 3
1 3 437
1 2 282
1 5 328
1 2 519
1 2 990
2 3 837
2 4 267
2 3 502
3 5 613
4 5 132
1 3 4
10 13 4
1 6 484
1 3 342
2 3 695
2 3 791
2 8 974
3 9 526
4 9 584
4 7 550
5 9 914
6 7 444
6 8 779
6 10 350
8 8 394
9 10 3 7
10 9 4
1 2 330
1 3 374
1 6 194
2 4 395
2 5 970
2 10 117
3 8 209
4 9 253
5 7 864
8 5 10 6  

样例输出:

40
60
90
70
90
8
30
70
100
10
9
81
63
1
4

数据范围:

技术图片

思路:

二进制拆分,对于拆出的每一位,0的放一边,1的放一边,将其中一组作为起点,都扔入队列中,每次跑到另外一组,记录最小的值,不关心是哪两点之间的最小值,对于每一位重复此步骤,一直取最小,最后输出答案。。

注意数的位数。。。。。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
#define MAXN 1000000
using namespace std;
bool v[MAXN],f[MAXN];
int T,n,m,k,per[MAXN],cnt,vis[MAXN],head[MAXN];
long long dist[MAXN],ans;
struct node{int to,nxt,dis;}e[MAXN<<1];
queue<int> q;
void add(int from,int to,int dis)
{
	e[++cnt].to=to;
	e[cnt].dis=dis;
	e[cnt].nxt=head[from];
	head[from]=cnt;
}
void spfa()
{
	for(int i = 1 ; i <= n ; i ++) dist[i] =2147483647;
	for(int i = 1;i <= k;i ++)
		if(f[i])
		dist[per[i]] = 0,q.push(per[i]),v[per[i]] = 1;
	while (!q.empty()){
		int x = q.front(); 
		q.pop();
		v[x] = 0;
		for(int i = head[x] ; i ; i = e[i].nxt){
			int y = e[i].to;
			int z = e[i].dis;
			if(dist[y] > dist[x] + z){
				dist[y] = dist[x] + z;
				if(!v[y])
				{
					q.push(y),v[y] = 1;
				}
			}
		}
	}
	for(int i = 1;i <= k;i ++)
		if(!f[i])
			ans = min(ans,dist[per[i]]);
}
int main()
{
	#ifdef yilnr
	#else
		freopen("hide.in","r",stdin);
		freopen("hide.out","w",stdout);
	#endif
	scanf("%d",&T);
	while(T--)
	{
		ans=2147483647;
		scanf("%d%d%d",&n,&m,&k);
		for(int i=1;i<=m;i++)
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			add(a,b,c);
			add(b,a,c);
		}
		for(int i=1;i<=k;i++)scanf("%d",&per[i]);	
		for(int j=0;j<=16;j++)
		{
			for(int i=1;i<=k;i++)
			{
				if((per[i]>>j) & 1) f[i] = 1;
				else f[i] = 0;
			}
			spfa();
		}
		if(ans==2147483647)printf("-1\n");
		else printf("%lld\n",ans);
		memset(head,0,sizeof(head));
		cnt=0;
	}
	fclose(stdin);fclose(stdout);
	return 0;
}

  

清北学堂-图论--二进制拆分--最短路--潜伏

标签:void   def   png   技术   进制   cstring   highlight   eof   mem   

原文地址:https://www.cnblogs.com/yelir/p/11360306.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!