给定一张 No,反之输出 Yes。保证询问中
考虑维护对于走每条边时需要多长时间才能连通最近的两个房子,换句话说,满足这个时间的时候这条边就一定可以被走。具体维护可以考虑建一个超级源点并向所有房子连个边,然后跑个 Dijk 即可,当然直接往队列里把所有房子点都塞进去也行。然后我们可以令
具体地,每次询问将边集里所有新的
同时不难想到即使
存在一道双倍经验 CF1253F Cheap Robot,略有区别,这里简单说一下:这道题的区别就在于询问的是最小的 clear() 之后 shrink_to_fit() 就会 TLE,否则会 MLE,按秩合并会保证合并询问的时候不会复制太多次以保证空间。这个东西的复杂度理论上似乎可以被卡到
xxxxxxxxxx96123
45678910
11using namespace std;12
13mt19937 rnd(random_device{}());14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}15bool rnddd(int x){return rndd(1, 100) <= x;}16
17typedef unsigned int uint;18typedef unsigned long long unll;19typedef long long ll;20typedef long double ld;21
22template < typename T = int >23inline T read(void);24
25struct Edge{26 Edge* nxt;27 int to;28 ll val;29 OPNEW;30}ed[410000];31ROPNEW(ed);32Edge* head[210000];33
34int N, M, K;35bitset < 210000 > vis;36ll dis[210000];37priority_queue < tuple < ll, int, int >, vector < tuple < ll, int, int > >, greater < tuple < ll, int, int > > > edgs;38
39class UnionFind{40private:41 int fa[210000];42public:43 UnionFind(void){for(int i = 1; i <= 201000; ++i)fa[i] = i;}44 int Find(int x){return x == fa[x] ? x : fa[x] = Find(fa[x]);}45 void Union(int origin, int son){fa[Find(son)] = Find(origin);}46}uf;47
48void Dijk(void){49 memset(dis, 0x3f, sizeof dis);50 priority_queue < pair < ll, int >, vector < pair < ll, int > >, greater < pair < ll, int > > > cur;51 for(int i = 1; i <= K; ++i)cur.push({dis[i] = 0, i});52 while(!cur.empty()){53 int p = cur.top().second; cur.pop();54 if(vis[p])continue;55 vis[p] = true;56 for(auto i = head[p]; i; i = i->nxt)57 if(dis[p] + i->val < dis[SON])58 dis[SON] = dis[p] + i->val, cur.push({dis[SON], SON});59 }60}61int main(){62 N = read(), M = read(), K = read();63 for(int i = 1; i <= M; ++i){64 int s = read(), t = read(), v = read();65 head[s] = new Edge{head[s], t, v};66 head[t] = new Edge{head[t], s, v};67 }Dijk();68 for(int p = 1; p <= N; ++p)69 for(auto i = head[p]; i; i = i->nxt)70 edgs.push({i->val + dis[p] + dis[SON], p, SON});71 int Q = read();72 while(Q--){73 int s = read(), t = read(); ll lim = read < ll >();74 while(!edgs.empty() && get < 0 >(edgs.top()) <= lim)75 uf.Union(get < 1 >(edgs.top()), get < 2 >(edgs.top())), edgs.pop();76 printf("%s\n", uf.Find(s) == uf.Find(t) ? "Yes" : "No");77 }78 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);79 return 0;80}81
82template < typename T >83inline T read(void){84 T ret(0);85 int flag(1);86 char c = getchar();87 while(c != '-' && !isdigit(c))c = getchar();88 if(c == '-')flag = -1, c = getchar();89 while(isdigit(c)){90 ret *= 10;91 ret += int(c - '0');92 c = getchar();93 }94 ret *= flag;95 return ret;96}update-2022_12_20 初稿