这两天Tarjan复习完后把题做了做。洛谷题单《图的连通性》已经做得差不多了。大部分是Tarjan的题,所以写一篇小总结。

T1 【模板】 缩点

不多bb。我已经写过关于Tarjan模板的随笔了。传送门

T2 【模板】割点

不多bb。传送门

T3 [USACO03FALL][HAOI2006]受欢迎的牛 G

题意简述:找到出度为0的点/强连通分量,并输出大小。

-----------------------------------------------------------------------------------

先缩点。值得注意的是图中只能有一个出度为0的点。如果有更多的出度为0的点那这些出度为0的点无法互相到达,那么数量就会为0。

数量在弹栈的时候记录就好。

代码:

#include<bits/stdc++.h>
using namespace std;
int head[],shabi;
int st[],top;
int vis[],dfn[],low[],all[],color[],du[];
int n,m,cnt,tot,x,y,k;
struct node
{
int next,to;
}edge[];
void add(int from,int to)
{
edge[++shabi].next=head[from];
edge[shabi].to=to;
head[from]=shabi;
}
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){
if (ch=='-') f=-;
ch=getchar();
}while(''<=ch&&ch<=''){
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
void tarjan(int now)
{
low[now]=dfn[now]=++cnt;
vis[now]=;
st[++top]=now;
for (int i=head[now];i;i=edge[i].next)
{
int to=edge[i].to;
if (!dfn[to]) tarjan(to),low[now]=min(low[now],low[to]);
else if (vis[to]) low[now]=min(low[now],dfn[to]);
}
if (dfn[now]==low[now]){
tot++;
do{
k=st[top];top--;
color[k]=tot;
vis[k]=;
all[tot]++;
}while(k!=now);
}
}
int main()
{
n=read(),m=read();
for (int i=;i<=m;i++)
{
x=read(),y=read();
add(x,y);
}
for (int i=;i<=n;i++) if(!dfn[i]) tarjan(i);
for (int w=;w<=n;w++)
for (int i=head[w];i;i=edge[i].next)
{
int to=edge[i].to;
if (color[w]!=color[to]) du[color[w]]++;
}
int flag=;
for (int i=;i<=tot;i++)
{
if (!du[i]){
if (flag){
cout<<;
return ;
}
flag=i;
}
}
cout<<all[flag];
return ;
}

T4 [USACO06JAN]The Cow Prom S

Tarjan裸题。只要把强连通分量的大小记录下来,如果$num[i]\geq 2$那么$ans++$。输出$ans$即可。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=;
const int maxm=;
int dfn[maxn],low[maxn],vis[maxn],num[maxn],pos[maxn],cnt,tot;
int st[maxn],top;
int head[maxm],jishu;
int n,m,ans;
struct node
{
int next,to;
}edge[maxm];
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if (ch=='-') f=-;ch=getchar();}
while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void add(int from,int to)
{
edge[++jishu].next=head[from];
edge[jishu].to=to;
head[from]=jishu;
}
void tarjan(int now)
{
vis[now]=;
st[++top]=now;
dfn[now]=low[now]=++cnt;
for (int i=head[now];i;i=edge[i].next)
{
int to=edge[i].to;
if (!dfn[to]) tarjan(to),low[now]=min(low[now],low[to]);
else if (vis[to]) low[now]=min(low[now],dfn[to]);
}
if (dfn[now]==low[now])
{
tot++;
while(st[top+]!=now)
{
pos[st[top]]=tot;
num[tot]++;
vis[st[top--]]=;
}
}
}
int main()
{
n=read(),m=read();
for (int i=;i<=m;i++)
{
int u=read(),v=read();
add(u,v);
}
for (int i=;i<=n;i++) if (!dfn[i]) tarjan(i);
for (int i=;i<=tot;i++) if (num[i]>) ans++;
printf("%d",ans);
return ;
}

T5 [USACO5.3]校园网Network of Schools

子问题1就是求缩点后入度为零的点的数量。子问题2就是求$max(ans1,ans2)$。

仔细读读题还是能明白要干什么的。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=;
const int maxm=;
int dfn[maxn],low[maxn],vis[maxn],pos[maxn],cnt,tot;
int st[maxn],top;
int head[maxm],jishu;
int n,fat[maxn][],k,in[maxn],out[maxn];
struct node
{
int next,to;
}edge[maxm];
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if (ch=='-') f=-;ch=getchar();}
while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void add(int from,int to)
{
edge[++jishu].next=head[from];
edge[jishu].to=to;
head[from]=jishu;
}
void tarjan(int now)
{
vis[now]=;st[++top]=now;
dfn[now]=low[now]=++cnt;
for (int i=head[now];i;i=edge[i].next)
{
int to=edge[i].to;
if (!dfn[to]) tarjan(to),low[now]=min(low[now],low[to]);
else if (vis[to]) low[now]=min(low[now],dfn[to]);
}
if (dfn[now]==low[now])
{
tot++;
while(st[top+]!=now)
{
pos[st[top]]=tot;
vis[st[top--]]=;
}
}
}
int main()
{
n=read();
for (int i=;i<=n;i++)
{
int x=read();
while(x!=)
{
add(i,x);
fat[++k][]=i;
fat[k][]=x;
x=read();
}
}
for (int i=;i<=n;i++) if (!dfn[i]) tarjan(i);
for (int i=;i<=k;i++)
if (pos[fat[i][]]!=pos[fat[i][]]) in[pos[fat[i][]]]++,out[pos[fat[i][]]]++;
int ans1=,ans2=;
for (int i=;i<=tot;i++)
{
if (in[i]==) ans1++;
if (out[i]==) ans2++;
}
if (tot==) cout<<<<endl<<;
else cout<<ans1<<endl<<max(ans1,ans2);
return ;
}

T6 上白泽慧音

在弹栈的时候记录强连通分量的大小和字典序就行了。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+;
const int inf=0x3f3f3f3f;
struct note{
int to,nex;
}e[maxn*];
int col,num,head[maxn],dfn[maxn],low[maxn],de[maxn],co[maxn],si[maxn],stk[maxn];
int top,n,m;
int cnt=-;
void add(int x,int y)
{
static int cnt=;
cnt++;
e[cnt].to=y;
e[cnt].nex=head[x];
head[x]=cnt;
} void tarjan(int u)
{
dfn[u]=low[u]=++num;
stk[++top]=u;
for(int i=head[u];i;i=e[i].nex)
{
int v=e[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(!co[v])low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
co[u]=++col;
++si[col];
while(stk[top]!=u)
{
++si[col];
co[stk[top]]=col;
--top;
}
--top;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int x,y,f;
cin>>x>>y>>f;
if(f==)add(x,y);
if(f==)add(x,y),add(y,x);
}
for(int i=;i<=n;i++)if(!dfn[i])tarjan(i);
for(int i=;i<=col;i++)cnt=max(cnt,si[i]);
cout<<cnt<<endl;
for(int i=;i<=n;i++)
{
if(si[co[i]]==cnt)
{
int now=co[i];
for(int j=i;j<=n;j++)if(co[j]==now)cout<<j<<" ";
return ;
}
}
return ;
}

后记:裸的Tarjan题还是很好看出解法的,但是和其他图论算法结合起来就十分难受了,有时候真的是绞尽脑汁也想不出来。

Tarjan 做题总结的更多相关文章

  1. UOJ 做题记录

    UOJ 做题记录 其实我这么弱> >根本不会做题呢> > #21. [UR #1]缩进优化 其实想想还是一道非常丝播的题目呢> > 直接对于每个缩进长度统计一遍就好 ...

  2. C语言程序设计做题笔记之C语言基础知识(下)

    C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...

  3. C语言程序设计做题笔记之C语言基础知识(上)

    C语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行事.并且C是相当灵活的,用于执行计算机程序能完成的几乎 ...

  4. 屏蔽Codeforces做题时的Problem tags提示

    当在Codeforces上做题的时,有时会无意撇到右侧的Problem tags边栏,但是原本并不希望能够看到它. 能否把它屏蔽了呢?答案是显然的,我们只需要加一段很短的CSS即可. span.tag ...

  5. ACM 做题过程中的一些小技巧。

    ACM做题过程中的一些小技巧. 1.一般用C语言节约空间,要用C++库函数或STL时才用C++; cout.cin和printf.scanf最好不要混用. 2.有时候int型不够用,可以用long l ...

  6. [日记&做题记录]-Noip2016提高组复赛 倒数十天

    写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...

  7. CodeM美团点评编程大赛复赛 做题感悟&题解

    [T1] [简要题意]   长度为N的括号序列,随机确定括号的方向:对于一个已确定的序列,每次消除相邻的左右括号(右左不行),消除后可以进一步合并和消除直到不能消为止.求剩下的括号的期望.\(N \l ...

  8. (luogu1704)寻找最优美做题曲线 [TPLY]

    寻找最优美做题曲线 题目链接:https://www.luogu.org/problemnew/show/P1704 题目大意: 求包含指定点的最长不降子序列(严格递增) 题解 首先我们发现 一个序列 ...

  9. project euler做题记录

    ProjectEuler_做题记录 简单记录一下. problem 441 The inverse summation of coprime couples 神仙题.考虑答案为: \[\begin{a ...

随机推荐

  1. day05 垃圾回收机制(超小白讲解)

    垃圾回收机制 在学习这个抽象概念前,老习惯,灵魂二问 什么是?为什么要有? 引言:在程序运行到变量定义时,会在内存空间中存放变量值,然而内存空间是有限的,变量是无限的. Q:如何在有限的内存里存里存放 ...

  2. day03 编程语言介绍

    一.编程语言分类 目录 一.编程语言分类 1.低级语言 1.1机器语言 1.2.汇编语言 2.高级语言 2.1编译型语言(例:c语言) 2.2解释型语言(例:世界上最好的语言python) 3总结 二 ...

  3. CSS的引入与选择器

    CSS的引入与选择器 CSS与HTML的关系 Cascading Style Sheet 即层叠样式表 在上一篇文中,已经介绍了一些非常常用的HTML标签,接下来将步入CSS的学习,如果将单纯HTML ...

  4. 记Centos7和RHEL连接不上网络

    一 .前言 我是把Linux系统安装在虚拟机中的,用的是VMware. 在终端工具和操作界面中. VMware里面采用的网络适配器是NAT技术. 标题中的Centos和RHEL区别就不多说了,自行百度 ...

  5. Java多线程详解总结

    一.基本概念 程序(program): 是为完成特定任务.用某种语言编写的一组指令的集合.即指一 段静态的代码,静态对象. 进程(process):是程序的一次执行过程,或是正在运行的一个程序.是一个 ...

  6. linux目录结构 主流Linux发行版的目录结构

    目录 目录结构 一般教学的目录 CentOS7 openSUSE15.1 Ubuntu18.04 详细说明: /dev目录 /etc目录 /proc目录 /usr目录 /var目录 比较重要的目录 文 ...

  7. Python Ethical Hacking - ARPSpoof_Detector

    ARPSPOOF_DETECTOR Watch value for gateway mac in the arp table Nice and simple, but will not detect ...

  8. bootstrap样式:.clearfix

    我们知道,在静态页面的编写中,清除浮动是一件很繁琐的事情. 所以一般的CSS框架都会有用来清除浮动的样式. 在bootstrap中,这个样式叫 clearfix. 只要在需要清除浮动的元素的父元素加上 ...

  9. Angular 的前世今生

    目录 序言 AngularJS 简介 Angular 2.0 的动机 现如今的 Angular Angular 的核心概念 参考 序言 Angular 一般意义上是指 Angular v2 及以上版本 ...

  10. 【JVM之内存与垃圾回收篇】运行时数据区概述及线程

    运行时数据区概述及线程 前言 本节主要讲的是运行时数据区,也就是下图这部分,它是在类加载完成后的阶段 当我们通过前面的:类的加载-> 验证 -> 准备 -> 解析 -> 初始化 ...