双log做法TLE #5~#7求卡常
查看原帖
双log做法TLE #5~#7求卡常
510555
ImposterAnYu楼主2024/10/5 16:50

qwq

#include <bits/stdc++.h>
#define int1 long long
#define N 100000
#define M 2000000
#define INF 1145141919810114514
#define P pair<int1,int1>
using namespace std;
int1 t,n,logn,m,k,i,j,ans,dis[N + 5],like[N + 5],lg,E;
bool b[N + 5];
int1 hea[N + 5],nex[M + 5],to[M + 5],w[M + 5],bs,qbs;
int1 read(){
	int1 x = 0,f = 1;
	char ch = getchar();
	while(!isdigit(ch)){
		if(ch == '-'){
			f = -1;
		}
		ch = getchar();
	}
	while(isdigit(ch)){
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return x * f;
}
void uprint(int1 x){
	if(x > 9){
		uprint(x / 10);
	}
	putchar(x % 10 ^ 48);
	return ;
}
void print(int1 x){
	if(x < 0){
		putchar('-');
		x = -x;
	}
	uprint(x);
	return ;
}
void ps(int1 x){
	print(x);
	putchar(' ');
	return ;
}
void pe(int1 x){
	print(x);
	putchar('\n');
	return ;
}
void add_edge(int1 x,int1 y,int1 z){
	nex[++bs] = hea[x],hea[x] = bs,to[bs] = y,w[bs] = z;
	return ;
}
void two_edge(int1 x,int1 y,int1 z){
	add_edge(x,y,z),add_edge(y,x,z);
	return ;
}
int1 dijkstra(int1 st,int1 ed){
	for(int1 i = 0; i <= E; i++){
		dis[i] = INF,b[i] = 0;
	}
	dis[st] = 0;
	priority_queue<P,vector<P >,greater<P > > q;
	q.push(make_pair(0,st));
	while(!q.empty()){
		int1 x = q.top().second;
		q.pop();
		if(b[x]){
			continue;
		}
		b[x] = 1;
		for(int1 i = hea[x]; i; i = nex[i]){
			int1 y = to[i],d = dis[x] + w[i];
			if(d < dis[y]){
				dis[y] = d;
				q.push(make_pair(d,y));
			}
		}
	}
	return dis[ed];
}
int1 solve(){
	n = read(),m = read(),k = read();
	E = n + 1;
	for(i = 1; i <= m; i++){
		int1 x = read(),y = read();
		add_edge(x,y,read());
	}
	qbs = bs;
	for(i = 1; i <= k; i++){
		like[i] = read();
	}
	int1 nn = n;
	while(nn){
		nn >>= 1;
		lg++;
	}
	ans = INF;
	for(i = 0; i < lg; i++){
		for(j = 1; j <= k; j++){//起点为0,终点为E=n+1
			if(like[j] & (1 << i)){
				add_edge(0,like[j],0);
			}else{
				add_edge(like[j],E,0);
			}
		}
		ans = min(ans,dijkstra(0,E));
		bs = qbs;//恢复原图
		hea[0] = 0;
		for(j = 1; j <= k; j++){
            if(!(like[j] & (1 << i))){
			    hea[like[j]] = nex[hea[like[j]]];
            }
		}
		for(j = 1; j <= k; j++){//因为是单向边,所以把点集互换重跑一遍
			if(like[j] & (1 << i)){
				add_edge(like[j],E,0);
			}else{
				add_edge(0,like[j],0);
			}
		}
		ans = min(ans,dijkstra(0,E));
		bs = qbs;
		hea[0] = 0;
		for(j = 1; j <= k; j++){
            if(like[j] & (1 << i)){
			    hea[like[j]] = nex[hea[like[j]]];
            }
		}
	}
	return ans;
}
int main(){
	t = read();
	while(t--){
		pe(solve());
		bs = 0;//清空图
		for(i = 1; i <= n; i++){
			hea[i] = 0;
		}
	}
	return 0;
}
2024/10/5 16:50
加载中...