标签: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