首页 > 其他分享 >题解 CF1873H Mad City

题解 CF1873H Mad City

时间:2023-09-23 09:11:12浏览次数:40  
标签:City 瓦勒 last 环上 int 题解 st Mad dis

题意描述

马塞尔和瓦勒里乌(Valeriu)所在的疯狂城市由 \(n\) 栋建筑和 \(n\) 条双向道路组成。

马塞尔和瓦勒里乌(Valeriu)分别从 \(a\) 号和 \(b\) 号建筑开始。马塞尔想赶上瓦勒里乌(换句话说,与他在同一栋楼里或在同一条路上相遇)。

在每次移动过程中,他们都会选择前往当前建筑的邻近建筑或留在同一建筑中。由于瓦勒里乌(Valeriu)对马塞尔(Marcel)非常了解,因此瓦勒里乌(Valeriu)可以预测马塞尔(Marcel)下次搬家时会去哪里。瓦勒里乌(Valeriu)可以利用这些信息进行移动。他们同时开始和结束移动。

可以保证任何一对建筑物之间都有路径相连,而且任何一对建筑物之间最多只有一条路。

假设两位棋手都以最优方式下棋,请回答瓦勒里乌(Valeriu)是否有无限期逃离马塞尔(Marcel)的策略。

具体思路

我们知道树是 \(n-1\) 条边的,因此再多加一条边,即 \(n\) 条边的话就会出现环。

设逃离抓捕的人为 \(s\),抓捕的人为 \(t\)。

根据样例 \(1\),我们发现,如果 \(s\) 在环上,那么 \(t\) 将永远无法抓到 \(s\)。

image

那么思路就很显然了。我们就是要尽量让 \(s\) 快一点跑到环上。这不就是最短路?

当然如果 \(s\) 一开始就在环上,那么就直接输出 YES 就好了。

我一开始的思路是先跑一遍 \(Tarjan\) 求出边双连通分量,即环。然后缩点,比较 \(s\) 和 \(t\) 到环的距离.

设 \(dist(x)\) 表示点 \(x\) 到环的距离。

若 \(dist(s) \ge dist(t)\),那么就是让 \(t\) 先到环上,那么输出 NO。

但是这种思路是有问题的。

image

如果 \(s\) 是 \(1\),\(t\) 是 \(5\),那么这两个点到环上的距离都是 \(1\) ,理应输出 NO,但是我们发现,\(s\) 跑到 \(2\) 后,由于他们没有重合,因此 \(t\) 将永远抓不到 \(s\)。

于是思路就变成了对 \(s\) 找到环上最近的点,然后找 \(t\) 到该点的距离,然后比较一下即可。

你可能会问 \(s\) 不会与环上多个点相连吗?显然是不会的,因为你要是和两个点相连,那么就有两个环了,那么总边数就不是 \(n\) 了。

设 \(s\) 到环上最近的点为 \(x\)。

至于找 \(t\) 到 \(x\) 的距离,由于题面的 \(n\) 是 \(2e5\),\(O(Tn\log n)\) 感觉过不去,于是我用 \(dfs\) 的方式来找 \(t\) 到 \(x\) 的距离。这样时间复杂度就是 \(O(Tn)\) 的,感觉可过。

然后就又发现问题了。

image

\(s\) 是 \(1\),\(t\) 是 \(7\),那么 \(s\) 到环上最近点 \(x\) 就是 \(3\)。你以为 \(t\) 到 \(3\) 的路径是 \(7-6-3\) 吗?不是!因为你是一个环,所以跑 \(dfs\) 的话有可能路径是 \(7-6-5-4-3\),这个时候你算出来的 \(t\) 到 \(x\) 的距离就会变长,答案也就错了。

因此只能用最短路了。用 spfa 显然是复杂度爆炸,于是采用 dijkstra 来看看能不能水过。最后过啦!

时间复杂度:\(O(Tn \log n)\)。

注意:

样例中有一组 \(s\) 和 \(t\) 重合的样例,直接输出 NO。记得一开始就要判掉。

Code

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
const int N=411000;
struct edge{int x,y,pre;}a[N];
int last[N],alen;
void ins(int x,int y){
	a[++alen]=edge{x,y,last[x]};
	last[x]=alen;
}
int dfn[N],low[N],id;
int bridge[N];
int cnt,c[N];
void tarjan(int x,int in_edge){
	dfn[x]=low[x]=++id;
	for(int k=last[x];k;k=a[k].pre){
		int y=a[k].y;
		if(!dfn[y]){
			tarjan(y,k);
			low[x]=min(low[x],low[y]);
			if(dfn[x]<low[y]){
				bridge[k]=bridge[k^1]=1;
			}
		}
		else if(k!=(in_edge^1)){
			low[x]=min(low[x],dfn[y]);
		}
	}
}
int bk;
void dfs(int x,int siz){
	c[x]=cnt;
	if(siz>1)bk=cnt;
	for(int k=last[x];k;k=a[k].pre){
		int y=a[k].y;
		if(c[y]||bridge[k])continue;
		dfs(y,siz+1);
	}
}
int v[N];
int dis_st,dis_ed,flag,d;
void dfs_st(int x,int dep){
	if(c[x]==bk){
		dis_st=dep;
		d=x;
		flag=1;
		return;
	}
	v[x]=1;
	for(int k=last[x];k;k=a[k].pre){
		int y=a[k].y;
		if(v[y])continue;
		dfs_st(y,dep+1);
		if(flag)return;
	}
}
int dis[N],vis[N];
void dijkstra(int st){
	memset(dis,0x3f,sizeof(dis));dis[st]=0;
	memset(vis,0,sizeof(vis));vis[st]=1;
	priority_queue<PII,vector<PII>,greater<PII>>Q;
	Q.push({0,st});
	while(!Q.empty()){
		int x=Q.top().second;Q.pop();
		for(int k=last[x];k;k=a[k].pre){
			int y=a[k].y;
			if(dis[y]>dis[x]+1){
				dis[y]=dis[x]+1;
				if(!vis[y]){
					vis[y]=1;
					Q.push({dis[y],y});
				}
			}
		}
		vis[x]=0;
	}
}
int main(){
	int t;scanf("%d",&t);
	while(t--){
		int n,st,ed;scanf("%d%d%d",&n,&ed,&st);
		alen=1;memset(last,0,sizeof(last));
		id=0;
		memset(dfn,0,sizeof(dfn));
		memset(low,0,sizeof(low));
		dis_st=0,dis_ed=0;
		cnt=0;d=0;bk=0;
		memset(c,0,sizeof(c));
		memset(bridge,0,sizeof(bridge));
		for(int i=1;i<=n;i++){
			int x,y;scanf("%d%d",&x,&y);
			ins(x,y);ins(y,x); 
		}
		if(st==ed){puts("NO");continue;}
		for(int i=1;i<=n;i++){
			if(!dfn[i])tarjan(i,0);
		}
		for(int i=1;i<=n;i++){
			if(!c[i]){
				cnt++;
				dfs(i,1);
			}
		}
		memset(v,0,sizeof(v));
		flag=0;dfs_st(st,0);
		dijkstra(ed);
		if(dis_st>=dis[d])puts("NO");
		else puts("YES");
	}
	return 0;
}

标签:City,瓦勒,last,环上,int,题解,st,Mad,dis
From: https://www.cnblogs.com/reclusive2007/p/17723861.html

相关文章

  • 'main' attribute cannot be used in a module that contains top-level code 问题解
    核心是@main注解在main.swift文件中,可以重新命名下参考资料https://stackoverflow.com/questions/73431031/swift-cli-app-main-attribute-cannot-be-used-in-a-module-that-contains-top-leve......
  • CF1842F Tenzing and Tree 题解
    TenzingandTree感觉很典型的题,就是树的重心+绝对值等式解法:以每个点\(i\)为根分别\(bfs\),得到一个距离数组\(dis\),取前\(k\)个值的权值为和,更新\(w[k]\)的值,\(n\)个点分别为根,更新\(n\)遍之后,得到\(w\)数组,则\((n-1)\timesi-w[i]\),即为\(i\)个点时候的......
  • 砝码称重 题解
    砝码称重题解前言这道题时限完全可以开到1s,空间也开不到1024kb白想那么多优化(不过这个复杂度可能是目前来看最合理(算出来保证能过)的。题意简述有一个长度为\(n\)的序列\(a\),有两种操作:把\(l\)到\(r\)的所有数改为\(x\);查询用\(l\)到\(r\)的所有数(每个数可......
  • 题解 AtCoder Beginner Contest 267 A~H
    ABC267solutionhttps://atcoder.jp/contests/abc267/ProblemA.Saturday题目描述输入一个表示星期的英文字符串,输出:还有多少天到星期六?solution依题意模拟。\(O(1)\)。ProblemB.Split?题目描述Robin有十个小球,如图排列成这样,然后Robin将一些球击飞了,他告诉你哪些......
  • Django跨域问题解决
    Django跨域问题解决今天在学习前端Vue框架的过程中,遇到了跨域相关问题问题1详情:AccesstoXMLHttpRequestat'http://127.0.0.1:8000/book/'fromorigin'http://localhost:63342'hasbeenblockedbyCORSpolicy:No'Access-Control-Allow-Origin'headerispre......
  • P5836 [USACO19DEC] Milk Visits S - 洛谷题解
     题目链接:[P5836] USACO19DEC] MilkVisitsS-洛谷|计算机科学教育新生态(luogu.com.cn)这道题可以用并查集来解决。题目中每个结点只有两个状态:H和G。那么我们可以推断出,只有当起点和终点间每个结点的状态相同但是起点(或者终点或起点到终点之间的某一点)与所需状态不同......
  • 苏格拉底问答,问题解决
     ......
  • 题解 P8670 [蓝桥杯 2018 国 B] 矩阵求和
    题目描述\[\sum_{i=1}^n\sum_{j=1}^n\gcd(i,j)^2\]具体思路solution1显然可以每次枚举\(\gcd(i,j)\)的取值。\[\sum_{k=1}^nk^2\sum_{i=1}^n\sum_{j=1}^n[\gcd(i,j)=k]\]令\(i=\lfloor\frac{i}{k}\rfloor\),\(j=\lfloor\frac{j}{k}\rfloor\)。\[\sum......
  • 1873H Mad City
    基环树上的“追及相遇”问题。考虑什么情况下,Valeriu能“无限期”地从Marcel手中逃离。参考样例1,我们发现当Valeriu进入基环树的环中,他总能通过预判,逃往Marcel的反方向,避免被抓;而如果两者都在子树中,Marcel就能步步紧逼,将Valeriu堵在叶子结点上——因此,Valeriu要尽快......
  • 【UVA 11175】From D to E and Back 题解(图论)
    取具有n个顶点和m条边的任意有向图D。你可以在以下方式。E将有m个顶点,每个顶点对应于D的每条边。例如,如果D有一条边uv,那么E将有一个叫做uv的顶点。现在,每当D有边uv和vw时,E就会有边顶点uv到顶点vw。E中没有其他边。你将得到一张E图,并且必须确定E是否有可能是某些有向图D的图的卧......