题目大意:给你n个点,m条无向边,每条边由Ai管理,边长为Bi,再给你K次操作,要顺序执行,可以选择跳过该操作或执行该操作,起点从1开始,要求从u->v这条路径属于当前这个操作的Ai, 并且边长累计(连续走的路径都由Ai管理且仍是第i个操作)不超过Bi,否则选择第i个操作之后第一个管理者是A,且边长大于等于B的操作执行。最后输出所有能走到的位置。
思路:思路很好想,用小顶堆存{第i张票序号、这张票已经走过的路程,顶点} ,每次遍历当前这个点的邻接点,如果与上一次的管理者相同则看这张票的剩余路程是否大于这条边的长度,否则就要查找[i+1,k]这个区间中第一个管理者为A,且长度大于等于B的票,可以通过对每个管理者的车票路程长度 B 建ST表,二分查找解决。
Code:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <cmath>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <limits.h>
#include <set>
#include <array>
#define int long long
using namespace std;
using aii =array<int,3>;
typedef pair<int,int> PII;
typedef pair<char,int> PCI;
typedef pair<string,aii> PSII;
#define fi first
#define se second
const int N=1e6+5;
int n,m,k;
int e[N],ne[N],c[N],w[N],idx,h[N];
int ans[N];
struct STList{
vector<vector<int>> stmax;
void init(vector<int>& a)
{
int len=a.size();
int K=__lg(len)+1;
stmax.assign(len,vector<int>(K));
for(int i=0;i<len;i++)
stmax[i][0]=a[i];
for(int j=1;j<K;j++)
{
for(int i=0;i+(1<<(j))-1<len;i++)
{
stmax[i][j]=max(stmax[i][j-1],stmax[i+(1<<(j-1))][j-1]);
}
}
}
int query(int l,int r)
{
int j=__lg(r-l+1);
return max(stmax[l][j],stmax[r-(1<<j)+1][j]);
}
};
void add(vector<int> &h,int a,int b,int c1,int d)
{
e[idx]=b,ne[idx]=h[a],w[idx]=d,c[idx]=c1,h[a]=idx++;
}
void solve()
{
cin>>n>>m>>k;
vector<int> h(2*m+5,-1);
// vector<int> ans(n+1,0);
// vector<bool> st(n+1,false);
idx=0;
vector<bool> st(n+1,false);
for(int i=1;i<=m;i++)
{
int a,b,c1,d;cin>>a>>b>>c1>>d;
add(h,a,b,c1,d),add(h,b,a,c1,d);
}
vector<vector<int> > q(m+1);
vector<vector<int>> q1(m+1);
vector<int> t(k+1),dis(k+1);
vector<STList> f(m+1);
t[0]=0;
for(int i=1;i<=k;i++)
{
int a,b;cin>>a>>b;
t[i]=a;
dis[i]=b;
q[a].push_back(b);
q1[a].push_back(i);
}
for(int i=1;i<=m;i++)
{
if(q[i].size())
f[i].init(q[i]);
}
priority_queue<aii,vector<aii>,greater<aii> > p;
p.push({0,0,1});
while(p.size())
{
auto [id,l,u]=p.top();p.pop();
if(st[u]) continue;
st[u]=1;
// cout<<"---"<<endl;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];//cout<<j<<endl;
if(c[i]==t[id])
{
if(dis[id]-l>=w[i])
{
p.push({id,l+w[i],j});
}
else
{
auto pp=upper_bound(q1[t[id]].begin(),q1[t[id]].end(),id);
if(pp!=q1[t[id]].end()){
int j1=pp-q1[t[id]].begin();
int r1=q1[t[id]].size()-1;
int L=j1,R=r1;
// cout<<"--- "<<f[t[id]].query(L,R)<<endl;
if(f[t[id]].query(L,R)<w[i]) continue;
while(L<R)
{
int mid=(L+R)>>1;
if(f[t[id]].query(j1,mid)>=w[i]) R=mid;
else L=mid+1;
}
p.push({q1[t[id]][R],w[i],j});
}
}
}
else
{
auto pp=upper_bound(q1[c[i]].begin(),q1[c[i]].end(),id);
if(pp!=q1[c[i]].end()){
int j1=pp-q1[c[i]].begin();
int r1=q1[c[i]].size()-1;
int L=j1,R=r1;
// cout<<"--- "<<f[c[i]].query(L,R)<<endl;
if(f[c[i]].query(L,R)<w[i]) continue;
while(L<R)
{
int mid=(L+R)>>1;
if(f[c[i]].query(j1,mid)>=w[i]) R=mid;
else L=mid+1;
}
p.push({q1[c[i]][R],w[i],j});
}
}
}
}
for(int i=1;i<=n;i++)
cout<<(st[i]?1:0);
cout<<endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int t;cin>>t;
// memset(h,-1,sizeof h);
//t=1;
while(t--) solve();
}