前言:没错,这题的名字就这么直白。我们考试题。

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

你需要完成$n$道题目。有一些题目是相关的,当你做一道题的时候,如果你做过之前对它有帮助的题目,你会更容易地做出它。当然,如果题目$x$对题目$y$有帮助,题目$y$并不一定对题目$x$有帮助。你可以自由安排做题顺序。现在,你想要知道,你在完成所有题目的情况下,可能有多少题目是在有帮助的情况下完成的。

请注意:帮助具有传递性,即$a$对$b$有帮助,$b$对$c$有帮助,那么$a$对$c$有帮助。

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

首先,我们考虑特殊情况。假设图是一条链。那么答案是$0-(n-1)$。

$0$:逆向走图。

$n-1$:顺向走图。

其他:“交流电”般地走。

如果图是多个连通块(多条链),答案显然是$0-k(n-1)$。

现在考虑有强连通分量的情况(一条链)。假设强连通分量的大小为$size$,那么可取的答案为$size-1$或$size$。

$size-1$表示从儿子走到父亲的情况。由于点都是互达的,所以只要到达一个点,其他点都是可达的。

$size$表示从父亲走到儿子。这时所有点都符合要求。

得到结论,答案范围为$\sum_{i=1}^k (size[i]-1)$到缩点之前点个数减缩点之后点个数。

现在考虑一般情况(一个连通块)。把它当成一条链显然会漏掉答案,因为此时图有可能是一个无根树。所以我们需要$dfs$,把这棵树分成许多链,再进行计算。

考虑有多个连通块且一般的情况,我们只需用到前面的结论然后遍历全图即可。

考虑文字比较抽象,我把自己的思路写出来。(字比较丑。大佬轻喷QAQ)

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=;
int cnt,dfn[maxn],vis[maxn],pos[maxn],low[maxn];
int st[maxn],top,tot;
int sum[maxn],size[maxn],num[maxn];
int jishu,head[maxn];
int n,m,x[maxn],y[maxn],du[maxn],chu[maxn];
int k,res;
struct node
{
int next,to,dis;
}edge[maxn];
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)
{
dfn[now]=low[now]=++cnt;
st[++top]=now;vis[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 (low[now]==dfn[now])
{
tot++;
while(st[top+]!=now)
{
pos[st[top]]=tot;
vis[st[top--]]=;
}
}
}
int dfs(int now)
{
if (!chu[now])
{
vis[now]=;cnt++;
return num[now];
}
cnt++;int ans=num[now];
for (int i=head[now];i;i=edge[i].next)
{
int to=edge[i].to;
if (vis[to]) continue;
vis[to]=;
ans+=dfs(to);
}
return ans;
}
void clear()
{
memset(vis,,sizeof(vis));
memset(head,,sizeof(head));
memset(edge,,sizeof(edge));
jishu=;cnt=;
}
int main()
{
n=read(),m=read();
for (int i=;i<=m;i++)
{
x[i]=read(),y[i]=read();
add(x[i],y[i]);
}
for (int i=;i<=n;i++) if (!dfn[i]) tarjan(i);
clear();
for (int i=;i<=n;i++) num[pos[i]]++;
for (int i=;i<=m;i++) if (pos[x[i]]!=pos[y[i]]) add(pos[x[i]],pos[y[i]]),du[pos[y[i]]]++,chu[pos[x[i]]]++;
for (int i=;i<=tot;i++)
{
if (du[i]) continue;
cnt=;k++;
sum[k]=dfs(i);size[k]=cnt;
res+=(sum[k]-size[k]);
}
//for (int i=1;i<=tot;i++) cout<<num[i]<<endl;
for (int i=res;i<=(n-k);i++) cout<<i<<endl;
return ;
}

【NOIP2015四校联训Day7】 题 题解(Tarjan缩点+DFS)的更多相关文章

  1. 福建工程学院第十四届ACM校赛M题题解 fwt进阶,手推三进制fwt

    第九集,结束亦是开始 题意: 大致意思就是给你n个3进制的数字,让你计算有多少对数字的哈夫曼距离等于i(0<=i<=2^m) 思路: 这个是一个防ak题,做法是要手推公式的fwt 大概就这 ...

  2. 福建工程学院第十四届ACM校赛G题题解

    外传:编剧说了不玩游戏不行 题意: 有n个石堆,我每次只能从某一堆中取偶数个石子,你取奇数个,我先手,先不能操作的人输.问最后谁能赢. 思路: 这个题仔细想想,就发现,取奇数的人有巨大的优势,因为假设 ...

  3. 福建工程学院第十四届ACM校赛B题题解

    第二集,未来的我发量这么捉急的吗 题意: 有n个数,请问有多少对数字(i,j)(1<=i<j<=n),满足(a[i]^a[j])+((a[i]&a[j])<<1) ...

  4. 福建工程学院第十四届ACM校赛J题题解

    第六集,想不到你这个浓眉大眼的都叛变革命了 题意: 给你两个只包含01的字符串S和T,问你在允许一次错误的情况下,T是否能成为S的子串 思路: 这个问题的解法挺多,我是用fft匹配的,也比较简单,针对 ...

  5. BZOJ5450: 轰炸(水题,Tarjan缩点求最长路)

    5450: 轰炸 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 43  Solved:18[Submit][Status][Discuss] Desc ...

  6. tarjan 缩点 + 几道例题

    tarjan 缩点 + 几道例题 tarjan 模板 #include <iostream> #include <string.h> using namespace std; ...

  7. 【bzoj1179】[Apio2009]Atm Tarjan缩点+Spfa最长路

    题目描述 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每 ...

  8. 2018 HDU多校第四场赛后补题

    2018 HDU多校第四场赛后补题 自己学校出的毒瘤场..吃枣药丸 hdu中的题号是6332 - 6343. K. Expression in Memories 题意: 判断一个简化版的算术表达式是否 ...

  9. 10.8 wtx模拟题题解

    填坑 orz w_x_c_q w_x_c_q的模拟赛(150pts,炸了) money 题目背景: 王小呆又陷入自己的梦里.(活在梦里...) 题目描述: 王小呆是一个有梦想的小菜鸡,那就是赚好多好多 ...

随机推荐

  1. 一篇文章掌握 Python 内置 zip() 的全部内容

    一篇文章掌握 Python 内置 zip() 的全部内容 zip() 是 Python 中最好用的内置类型之一,它可以接收多个可迭代对象参数,再返回一个迭代器,可以把不同可迭代对象的元素组合起来. 我 ...

  2. VSCode下,项识别为 cmdlet、函数、脚本文件或可运行程序的名称。

    vscode下webpack错误:无法将“webpack”项识别为 cmdlet.函数.脚本文件或可运行程序的名称.请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次. 解决方法: 1.因为 ...

  3. 数据可视化基础专题(五):Pandas基础(四) 生成对象

    引言 先介绍下 Pandas 的数据结构,毕竟数据结构是万物的基础. Pandas 有两种主要的数据结构: Series 和 DataFrame 模块导入 首先我们在代码中引入 Pandas 和 Nu ...

  4. node最简单的本地服务搭建

    **1.首先需要安装node** [node下载链接](http://nodejs.cn/download/)**2.需要安装http的镜像文件** npm install http-server - ...

  5. CSS文本溢出,显示省略号(...)

    方式1:这种方式就是必须要跟width搭配使用,当你使用的display:flex; 的时候可能会影响样式 width: 200px; overflow: hidden; /*超出部分隐藏*/ tex ...

  6. [Antd-vue] Warning: You cannot set a form field before rendering a field associated with the value.

    在用ant-design-vue的框架中,使用到了这种场景,就是点击编辑按钮,弹出modal模态框,渲染modal模态框中的form表单页面,并给表单赋值,但是在给表单赋值的时候,总是会报错. 错误提 ...

  7. Ethical Hacking - GAINING ACCESS(1)

    Gaining Access Introduction Everything is a computer Two main approaches (1)Server Side Do not requi ...

  8. SQL数据多条转单条(CONCAT_WS)

    一.concat()函数可以连接一个或者多个字符串 concat(str1,str2,…) 返回结果为连接参数产生的字符串.如有任何一个参数为NULL ,则返回值为 NULL. select conc ...

  9. 关于C#反射(转载)

    反射的用途:     (1)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例.     (2)使用Module了解包含模块的程序集以及模块中 ...

  10. 拿不到offer?阿里HR教你简历应该这样写

    首先,要明白公司看重的是你的什么?为什么要聘请你?当然是看重你的能力,聘请你来是要来干活的. 都知道简历是敲门砖,那么这一块砖要怎么才能敲得响,怎么才能敲得开大厂的门. 1 能力萃取!什么是能力萃取? ...