神奇的建图方式(Tarjan)——小z玩游戏
2024-09-07 17:35:06
原题来自与:洛谷 P5676(GZOI2017) 链接: https://www.luogu.com.cn/problem/P5676
题面:
题意比较明显,如果已经建好了边,那么跑个Tarjan 就完了。
但是问题在于建边的复杂度,比较好想的是n2 的建边方式。
但是时间肯定不允许。
那么我们就要想一种时间复杂度较小的建边方式。
可以考虑引入中间变量兴奋程度
那么如何建边,
首先将点开多一些
把中间变量兴奋程度也当作点
然后建边
1.建一个由 有趣程度 到 点 的边
2.建一个由 点 到 兴奋程度 的边
3.重点:建一个兴奋程度整数倍的边。
然后就跑一边tarjan就完了,
下面是代码(加注释):
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=500005*4;
int n;
int Max=0;
struct edge{
int to,next;
}e[maxn];int head[maxn],cnt=0;
void add(int x,int y){
e[++cnt].to=y;e[cnt].next=head[x];head[x]=cnt;
}
int w[maxn],b[maxn];
int dfn[maxn],low[maxn],dfs_clock,sta[maxn],top,belong[maxn],siz[maxn],vis[maxn],dcc;
void dfs(int u){
dfn[u]=low[u]=++dfs_clock;
sta[++top]=u;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(!dfn[v]){
dfs(v);
low[u]=min(low[u],low[v]);
}
else if(!belong[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){//特殊的出栈方式
dcc++;
belong[u]=dcc;
siz[dcc]++;
while(sta[top]!=u){
int x=sta[top--];
belong[x]=dcc;
siz[dcc]++;
vis[x]=1;
}
if(siz[dcc]>1)vis[u]=1;
top--;
}
}
void clear(){
memset(e,0,sizeof(e));
memset(head,0,sizeof(head));
cnt=0;Max=0;
memset(w,0,sizeof(w));
memset(b,0,sizeof(b));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
dfs_clock=0;
memset(sta,0,sizeof(siz));
top=0;
memset(belong,0,sizeof(belong));
memset(siz,0,sizeof(siz));
memset(vis,0,sizeof(vis));
dcc=0;
}
int main(){
//freopen("a.in","r",stdin);
int t;scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&w[i]);
add(n+w[i],i);
Max=max(Max,w[i]);//建第一种边
}
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
add(i,n+b[i]);//见第二种边
}
for(int i=1;i<=Max;i++){
for(int j=2;j*i<=Max;j++){//第三种边
add(i+n,j*i+n);
}
}
if(n==1){//数据特判,详见样例1
printf("1\n");clear();continue;
} for(int i=1;i<=n;i++){//tarjan
if(!dfn[i])dfs(i);
}
int ans=0;
for(int i=1;i<=n;i++){//判断答案,注意只要1——n的点
if(vis[i])ans++;
}
printf("%d\n",ans);
clear();
}
return 0;
}
希望大家能学会这种神奇的建边方式
最新文章
- 控制TextField的内容长度
- 你不知道的Javascript(上卷)读书笔记之一 ---- 作用域
- ArrayList如何实现线程安全
- 安装docker-compose
- SuperSocket 1.6.4 通过FixedHeaderReceiveFilter解析自定义协议
- require.js的用法
- 数据访问层DAL(数据库访问抽象类DataProvider)
- ip头、tcp头、udp头详解及定义,结合Wireshark抓包看实际情况
- Oracle监控指标
- java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)
- CNCC2017梳理
- JAVA工程师面试题【来自并发编程网】
- Hper-V卸载
- 【笔记】Python基础一 :变量,控制结构,运算符及数据类型之数字,字符串,列表,元组,字典
- 48-Python 安装pyautogui失败解决办法
- 用C++的 new 代替 C 的 malloc 进行内存分配
- libgdx学习记录16——资源加载器AssetManager
- Aheadof Time Compilation(AOT) vs (JIT)Just In Time compilation approach
- PHP数组合并:[“+”运算符]、[array_merge]、[array_merge_recursive]区别
- MyBatis(1)优点&;介绍&;工程