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


    样例输入:

    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
    ");
    		else printf("%lld
    ",ans);
    		memset(head,0,sizeof(head));
    		cnt=0;
    	}
    	fclose(stdin);fclose(stdout);
    	return 0;
    }
    

      

  • 相关阅读:
    常量池 栈 堆
    函数的调用
    字符、数组
    整理
    JavaScript深入之——原型与原型链
    虚拟机(VMware)中文破解版,及创建虚拟机
    小程序之mpvue使用
    报错整理及解决办法
    js 关于时间方面的通用函数
    iview Cascader级联选择省市区问题
  • 原文地址:https://www.cnblogs.com/yelir/p/11360306.html
Copyright © 2020-2023  润新知