P10206 题解

题意不再赘述。

解法

不妨先在图上分别把以 S,T 为起点到各点的最短路跑出来,记为 dsu,dtu

dsTK,则答案为 N(N1)2,这是显然的。

否则,考虑一下,当什么条件下,在 (u,v) 间修建铁路能满足条件,无非是以下两种:

  • u<v,dsu+L+dtvK
  • u<v,dsv+L+dtuK

我们只讨论前者的统计方法,后者同前者。

变形,我们要对于每一个 v 统计满足 dtuKLdsvu 的个数。这个可以把值域离散化,再开一个树状数组来统计。

具体地,我们把所有的 dtuKLdsv 离散化。让 i=1,2,3,,N,则对于每个 i,答案加上树状数组上 KLdsv 的前缀和,再把树状数组上 dti 的位置增加 1

这样就可以在 O((M+N)logN) 内解决问题。

代码注意 long long

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fi first
#define se second
const int N=2e5+10;
ll n,m,s,t;
ll l,k;
struct edge{
	int v,nxt;
	ll w;
}e[N*2];
int head[N],cnt=2;
void add(int u,int v,ll w){
	e[cnt].v=v,e[cnt].w=w;
	e[cnt].nxt=head[u];
	head[u]=cnt++;
}
ll ds[N],dt[N];
bool vis[N];
void Dijkstra(ll d[],int s){
	memset(d,0x3f,sizeof(ll)*(n+10));
	memset(vis,0,sizeof(vis));
	priority_queue<pair<ll,int> >q;
	q.push(make_pair(0,s));
	d[s]=0;
	while(q.size()){
		int u=q.top().se;q.pop();
		if(vis[u])continue;
		vis[u]=1;
		for(int i=head[u];i;i=e[i].nxt){
			if(!vis[e[i].v]&&d[e[i].v]>d[u]+e[i].w){
				d[e[i].v]=d[u]+e[i].w;
				q.push(make_pair(-d[e[i].v],e[i].v));
			}
		}
	}
}
ll dis[N*2],tot;
ll bit[N*2];
inline int lowbit(int x){return x&(-x);}
void upd(int p,ll x){for(;p<=tot;p+=lowbit(p))bit[p]+=x;}
ll ask(int p){ll ans=0;for(;p;p-=lowbit(p))ans+=bit[p];return ans;}
ll ans=0;
int dsk(ll x){return lower_bound(dis+1,dis+1+tot,x)-dis;}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0); 
	cin>>n>>m>>s>>t>>l>>k;
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		add(u,v,w);
		add(v,u,w);
	}
	Dijkstra(ds,s);
	Dijkstra(dt,t);
	if(ds[t]<=k){
		cout<<n*(n-1)/2<<'\n';
		return 0;
	}
	for(int i=1;i<=n;i++)dis[++tot]=dt[i];
	for(int i=1;i<=n;i++){
		if(ds[i]+l<=k){
			dis[++tot]=k-l-ds[i]; 
		}
	}
	sort(dis+1,dis+1+tot);
	tot=unique(dis+1,dis+1+tot)-dis-1;
	for(int i=1;i<=n;i++){
		if(ds[i]+l<=k)
			ans+=ask(dsk(k-l-ds[i]));
		upd(dsk(dt[i]),1);
	}
	memset(bit,0,sizeof(bit));tot=0;
	
	for(int i=1;i<=n;i++)dis[++tot]=ds[i];
	for(int i=1;i<=n;i++){
		if(dt[i]+l<=k){
			dis[++tot]=k-l-dt[i]; 
		}
	}
	sort(dis+1,dis+1+tot);
	tot=unique(dis+1,dis+1+tot)-dis-1;
	for(int i=1;i<=n;i++){
		if(dt[i]+l<=k)
			ans+=ask(dsk(k-l-dt[i]));
		upd(dsk(ds[i]),1);
	}
	cout<<ans<<'\n';
	return 0;
}
posted @   Linge_Zzzz  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示