题意:

  给一些集合 要求证明所有集合是相同的

  证明方法是,如果$A∈B$,$B∈A$那么$A=B$成立

  每一次证明可以得出一个$X∈Y$

  现在已经证明一些$A∈B$成立

  求,最少再证明多少次,就可以完成要求

分析

  其实就等价于给一个有向图,问你再加入多少个边可以使得图变为强连通图

  给一个图论经典结论:

  "对于一个有向无环图(DAG),若想让它成为强连通图,至少需要添加$max(a,b)$条边 $a$为入度为0的点的数量,$b$为出度为0的点的数量"

  而对于一个有向图,其每个强连通分量都互相可达,也就是只要到达任意一个点,即可到达内部所有的点

  现在,只要对于强连通分量进行缩点,再新图中统计出入度数即可得到答案

  *注意,如果强连通分量只有1个,答案应该是0而不是1

#include <bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pp pair<int,int>
#define rep(ii,a,b) for(int ii=a;ii<=b;ii++)
#define per(ii,a,b) for(int ii=a;ii>=b;ii--)
#define show(x) cout<<#x<<"="<<x<<endl
#define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
#define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define showa(a,b) cout<<#a<<'['<<#b<<"]="<<a[b]<<endl
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
int stk[maxn],top,cnt,dfn[maxn],low[maxn],numc,belong[maxn],vis[maxn];
struct node {int to,cost,next;}e[maxm];int head[maxn],nume;
void add(int a,int b,int c=1){e[++nume]=(node){b,c,head[a]};head[a]=nume;}
void tdfs(int now){
dfn[now]=low[now]=++cnt;
stk[top++]=now;
vis[now]=1;
for(int i=head[now];i;i=e[i].next){
int to=e[i].to;
if(!dfn[to]){tdfs(to);low[now]=min(low[now],low[to]);}
else if(vis[to]) low[now]=min(low[now],dfn[to]);
}
if(low[now]==dfn[now]){
numc++;
int to;
do{
to=stk[--top];
belong[to]=numc;
vis[to]=0;
}while(to!=now);
}
}
void tarjan(int numv=n){
for(int i=1;i<=numv;i++){
if(!dfn[i]) tdfs(i);
}
}
void ginit(){
nume=top=numc=cnt=0;
memset(head,0,sizeof head);
memset(dfn,0,sizeof dfn);
}
int din[maxn],dout[maxn]; int main(){
//#define test
#ifdef test
freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif while(cin>>n>>m){
if(m==0) {
cout<<n<<endl;
continue;
}
ginit();
memset(din,0,sizeof din);
memset(dout,0,sizeof dout);
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
add(a,b);
}
tarjan();
for(int i=1;i<=n;i++){
for(int j=head[i];j;j=e[j].next){
if(belong[i]==belong[e[j].to])continue;
dout[belong[i]]++;
din[belong[e[j].to]]++;
}
}
int a=0,b=0;
for(int i=1;i<=numc;i++){
if(din[i]==0)a++;
if(dout[i]==0)b++;
}
if(numc==1) a=b=0;
cout<<max(a,b)<<endl;
} #ifdef test
fclose(stdin);fclose(stdout);system("out.txt");
#endif
return 0;
}

  

Equivalent Sets HDU - 3836 2011多校I tarjan强连通分量的更多相关文章

  1. Equivalent Sets HDU - 3836 (Tarjan)

    题目说给出一些子集,如果A是B的子集,B是A的子集,那么A和B就是相等的,然后给出n个集合m个关系,m个关系表示u是v的子集,问你最小再添加多少个关系可以让这n个集合都是相等的 如果这n个几个都是互相 ...

  2. HDU 1269 迷宫城堡(判断有向图强连通分量的个数,tarjan算法)

    迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  3. HDU 4685 Prince and Princess(二分图+强连通分量)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:给出n个王子和m个公主.每个王子有一些自己喜欢的公主可以匹配.设最大匹配为M.那么对于每个 ...

  4. HDU 3861 The King’s Problem(强连通分量+最小路径覆盖)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 题目大意: 在csdn王国里面, 国王有一个新的问题. 这里有N个城市M条单行路,为了让他的王国 ...

  5. HDU 3861 The King's Problem(强连通分量缩点+最小路径覆盖)

    http://acm.hdu.edu.cn/showproblem.php?pid=3861 题意: 国王要对n个城市进行规划,将这些城市分成若干个城市,强连通的城市必须处于一个州,另外一个州内的任意 ...

  6. 【BZOJ2438】 [中山市选2011]杀人游戏 tarjan强连通分量+缩点

    Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是 ...

  7. 【(最小权点基)tarjan强连通分量缩点+tarjan模板】HDU 5934 Bomb

    [AC] #include<bits/stdc++.h> using namespace std; typedef long long ll; int n; ; ; const int i ...

  8. HDU - 1269 迷宫城堡(有向图的强连通分量)

    d.看一个图是不是强连通图 s.求出强连通分量,看看有没有一个强连通分量包含所有点. c.Tarjan /* Tarjan算法 复杂度O(N+M) */ #include<iostream> ...

  9. [tarjan] hdu 3836 Equivalent Sets

    主题链接: http://acm.hdu.edu.cn/showproblem.php? pid=3836 Equivalent Sets Time Limit: 12000/4000 MS (Jav ...

随机推荐

  1. 02-Unity深入浅出(二)

    一. Unity声明周期 Unity容器为我们提供了6种生命周期,便于我们根据项目需求来选择使用. (1). 瞬时.默认省略即为瞬时,无论单线程还是多线程,每次都重新创建对象.new Transien ...

  2. 修改VS 2012调试默认浏览器

    首先用vs打开我们的工程文件,点击任意一个aspx文件,点右键,找到弹出菜单中的“浏览方式”,如图: 然后点击“浏览方式”或者“Browser with”,弹出如图对话框: 

  3. gethostbyname和gethostbyaddr

    一.gethostbyname函数原型 #include <netdb.h> struct hostent *gethostbyname(const char *ghostname); 返 ...

  4. 求f(n)=[n/1]+[n/2]+---+[n/n]的值 简单杂题

    这种小题首先根据 n/1+n/2+n/3+--+n/n=nlogn+欧拉常数r 可以知道 1e12的范围也不会爆longlong,不需要写高精度(到现在都不会写) 再根据数据范围可知O(n)级别的暴力 ...

  5. 如何修改Jupyter Notebook的主题

    1.windows系统 (1)下载到本地(使用git bash命令行界面) git clone https://github.com/dunovank/jupyter-themes (2)Instal ...

  6. 剑指offer: 数组中的逆序对

    1. 最简单的思路,对每个值,遍历与其逆序的数组对:但时间复杂度太高: 2. 归并排序的思路: 先将数组分隔成子数组,先统计出子数组内的逆序对的数目,然后统计两个相邻子数组之间的逆序对的数目: int ...

  7. matplotlib-形状

    需要   import matplotlib.patches as mp import numpy as np import matplotlib.pyplot as plt import matpl ...

  8. jstl-----之<set>标签

    <table id="attachtab" border="0" cellpadding="0" cellspacing=" ...

  9. Python 包

    转载自https://www.cnblogs.com/feeland/p/4401758.html Python 包 包 定义 为了组织好模块,会将多个模块分为包.Python 处理包也是相当方便的. ...

  10. lateinit 的使用限制

    呢?使用lateinit关键字 lateinit var test:String //正确lateinit val test:String //错误lateinit var test:Float // ...