P5676 [GZOI2017]小z玩游戏 Tarjan+优化建图
题目描述




分析
一开始看到这道题,首先想到的就是建好边后跑一个Tarjan缩点,将siz大于1的节点统计一下,输出结果
Tarjan非常显然易得,关键就是怎么建边
比较好想的一种思路就是枚举每一个兴奋程度
对于每一个兴奋程度,再将有趣程度枚举一遍
如果有趣程度是兴奋程度的倍数的话,在两个节点之间建一条有向边
我们拿第二个样例模拟一下,建好边后就是下面这样

那么缩点后大小不为1的强连通分量只有一个,它的大小为3
那么最终的答案就是\(3\)
但是这样的建边效率为\(n^2\),复杂度接受不了
所以我们考虑更优秀的建边方法
这里要用到的是建虚点的方法
1.建一个由 有趣程度 到 点 的边
2.建一个由 点 到 兴奋程度 的边
3.重点:建一个兴奋程度整数倍的边
要注意的是建虚点的时候,要把游戏的编号加上一个\(n\)
避免和原先的编号重复
然后思路就和\(n^2\)的解法一样
至于时间复杂度,根据大佬的证明,是

代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+5;
struct asd{
int from,to,next;
}b[maxn];
int head[maxn],tot=1;
void ad(int aa,int bb){
b[tot].from=aa;
b[tot].to=bb;
b[tot].next=head[aa];
head[aa]=tot++;
}
int dfn[maxn],low[maxn],top,sta[maxn],dfnc,shuyu[maxn],siz[maxn],js,vis[maxn];
void tar(int xx){
dfn[xx]=low[xx]=++dfnc;
sta[++top]=xx;
for(int i=head[xx];i!=-1;i=b[i].next){
int u=b[i].to;
if(!dfn[u]){
tar(u);
low[xx]=min(low[xx],low[u]);
} else if(!shuyu[u]){
low[xx]=min(low[xx],dfn[u]);
}
}
if(low[xx]==dfn[xx]){
js++;
siz[js]=1;
while(sta[top]!=xx){
int now=sta[top--];
shuyu[now]=js;
siz[js]++;
vis[now]=1;
}
top--;
shuyu[xx]=js;
if(siz[js]>1) vis[xx]=1;
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(head,-1,sizeof(head));
memset(&b,0,sizeof(struct asd));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
tot=1,js=0,dfnc=0,top=0;
memset(vis,0,sizeof(vis));
memset(sta,0,sizeof(sta));
memset(shuyu,0,sizeof(shuyu));
memset(siz,0,sizeof(siz));
int n;
scanf("%d",&n);
int mmax=0;
for(int i=1;i<=n;i++){
int aa;
scanf("%d",&aa);
ad(n+aa,i);
mmax=max(mmax,aa);
}
for(int i=1;i<=n;i++){
int aa;
scanf("%d",&aa);
ad(i,n+aa);
}
for(int i=1;i<=mmax;i++){
for(int j=2;j*i<=mmax;j++){
ad(n+i,n+i*j);
}
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tar(i);
}
int ans=0;
for(int i=1;i<=n;i++){
if(vis[i]==1) ans++;
}
printf("%d\n",ans);
}
return 0;
}
P5676 [GZOI2017]小z玩游戏 Tarjan+优化建图的更多相关文章
- P5676 [GZOI2017]小z玩游戏【Tarjan】
小z玩游戏 Tarjan算是板子题吧,但是要稍微做一些修改,建边需要多考虑,建立"虚点". 题目描述 小 z 很无聊. 小 z 要玩游戏. 小 z 有\(N\)个新游戏,第\(i\ ...
- 【题解】 [GZOI2017]小z玩游戏
题目戳我 \(\text{Solution:}\) 考虑建图.操作可以看作对\(1\)进行的操作,于是有以下运行过程: \(1\to w[i]\to e[i]\to...\) 考虑倍数,一个数可以走到 ...
- 神奇的建图方式(Tarjan)——小z玩游戏
原题来自与:洛谷 P5676(GZOI2017) 链接: https://www.luogu.com.cn/problem/P5676 题面: 题意比较明显,如果已经建好了边,那么跑个Tarjan ...
- 二分图【洛谷P2175】 小Z的游戏分队
P2175 小Z的游戏分队 小Z受不了寂寞,准备举办一次DOTA比赛,为了能让ACM班全部都参加比赛,他还特制了一张DOTA地图能够支持任意多人打任意多人. 现在问题来了,怎么把这么多人分成两队?小Z ...
- JZOJ 5777. 【NOIP2008模拟】小x玩游戏
5777. [NOIP2008模拟]小x玩游戏 (File IO): input:game.in output:game.out Time Limits: 1000 ms Memory Limits ...
- 2783: 【基础】小 X 玩游戏(game)
2783: [基础]小 X 玩游戏(game) 时间限制: 1 Sec 内存限制: 64 MB 提交: 752 解决: 294 [提交] [状态] [讨论版] [命题人:ghost79] 题目描述 听 ...
- AtCoder Regular Contest 069 F Flags 二分,2-sat,线段树优化建图
AtCoder Regular Contest 069 F Flags 二分,2-sat,线段树优化建图 链接 AtCoder 大意 在数轴上放上n个点,点i可能的位置有\(x_i\)或者\(y_i\ ...
- BZOJ 4289 最短路+优化建图
题意:给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价.起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边权. 解法:参考h ...
- BZOJ 4276 [ONTAK2015]Bajtman i Okrągły Robin 费用流+线段树优化建图
Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2],...,[b[i]-1,b[i]]这么多段长度为1时间中选出一个时间进行抢劫,并计划抢 ...
随机推荐
- Swift 语法总结
1,用 var 定义变量 ,与js类似. let 用于定义常量,定义完后不能修改. var 用于定义变量,可以修改. swift可以自动识别属性类别. 2,使用 import 语句来引入任何的 Obj ...
- 深入理解Java的动态编译
前提 笔者很久之前就有个想法:参考现有的主流ORM框架的设计,造一个ORM轮子,在基本不改变使用体验的前提下把框架依赖的大量的反射设计去掉,这些反射API构筑的组件使用动态编译加载的实例去替代,从而可 ...
- Java创建ES索引实现
1.pom.xml文件 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...
- 【asp.net core 系列】8 实战之 利用 EF Core 完成数据操作层的实现
0. 前言 通过前两篇,我们创建了一个项目,并规定了一个基本的数据层访问接口.这一篇,我们将以EF Core为例演示一下数据层访问接口如何实现,以及实现中需要注意的地方. 1. 添加EF Core 先 ...
- ubuntu opensips环境搭建
1.安装前准备,需要安装如下工具: perl. libdbi-perl. libdbd-mysql-perl. libdbd-pg-perl. libfrontier-rpc-perl. libter ...
- git新手入门问题总结
git新手入门问题总结 前言 本人为2019年6月份刚刚毕业,大三暑假中旬来到上海,实习时间大致为十个月,在这十个月里面学到了许多关于git使用方面的知识 经常会逛开源中国水水动态,看看技术帖子学习知 ...
- 从0到70%:Chrome上位揭秘!
最近的数据显示,Chrome在2020年4月的市场份额达到了70%左右,把微软的Edge和Firefox远远甩在身后,毫无疑问,Chrome赢得了第二次游览器之战,成为新一代王者. Chrome的第一 ...
- VS Code项目中通过npm包的方式共享代码片段的方案实现
VS Code项目中通过npm包的方式共享代码片段的方案实现 上周在 "VS Code项目中共享自定义的代码片段方案" 的文章中提到过一个共享代码片段的方案,上周经过调研后并没有发 ...
- c常用函数-strlen
strlen 返回字符串长度 Action() { char test[] = "yyyHHHJJJoo"; unsigned int a; a = strlen(test); l ...
- DS-4-单链表的各种插入与删除的实现
typedef struct LNode { int data; struct LNode *next; }LNode, *LinkList; 带头结点的按位序插入: //在第i个位置插入元素e bo ...