# Equivalent Sets

Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Others)
Total Submission(s): 3619    Accepted Submission(s): 1262

Problem Description
To prove two sets A and B are equivalent, we can first prove A is a subset of B, and then prove B is a subset of A, so finally we got that these two sets are equivalent.
You are to prove N sets are equivalent, using the method above: in each step you can prove a set X is a subset of another set Y, and there are also some sets that are already proven to be subsets of some other sets.
Now you want to know the minimum steps needed to get the problem proved.

Input
The input file contains multiple test cases, in each case, the first line contains two integers N <= 20000 and M <= 50000.
Next M lines, each line contains two integers X, Y, means set X in a subset of set Y.

Output
For each case, output a single integer: the minimum steps needed.

Sample Input
4 0 3 2 1 2 1 3

Sample Output
4 2
Hint
Case 2: First prove set 2 is a subset of set 1 and then prove set 3 is a subset of set 1.

Source

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=100010;
int dfs_clock,scc_cnt;
int sccno[maxn];
int low[maxn],dfn[maxn];
bool instack[maxn];
int in[maxn],out[maxn];
stack<int>S;
vector<int>scc[maxn];
vector<int>G[maxn];
struct Node{
int from,to,next;
}A[maxn];
int MAX(int a,int b){
return a>b?a:b;
}
int MIN(int a,int b){
return a<b?a:b;
}
void init(){
dfs_clock=scc_cnt=0;
memset(sccno,0,sizeof(sccno));
memset(instack,false,sizeof(instack));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
}
void tarjan(int u,int pre){
int v;
dfn[u]=low[u]=++dfs_clock;
S.push(u);instack[u]=true;
v=A[k].to;
if(!dfn[v]){
tarjan(v,u);
low[u]=MIN(low[u],low[v]);
}
else if(instack[v]){
low[u]=MIN(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
scc_cnt++;scc[scc_cnt].clear();
G[scc_cnt].clear();
while(1){
v=S.top();S.pop();
instack[v]=false;
scc[scc_cnt].push_back(v);
sccno[v]=scc_cnt;
if(u==v)break;
}
}
}
void suodian(int m){
for(int i=0;i<m;++i){
int u=sccno[A[i].from];
int v=sccno[A[i].to];
if(u!=v){
G[u].push_back(v);
in[v]++;out[u]++;
}
}
}
int main()
{
int i,j,k,n,m;
while(scanf("%d%d",&n,&m)!=EOF){
init();
for(i=0;i<m;++i){
scanf("%d%d",&A[i].from,&A[i].to);
}
for(i=1;i<=n;++i){
if(!dfn[i]){
tarjan(i,-1);
}
}
if(scc_cnt==1){
printf("%d\n",0);
continue;
}
suodian(m);
int ans1=0,ans2=0;
for(i=1;i<=scc_cnt;++i){
if(in[i]==0)ans1++;
if(out[i]==0)ans2++;
}
printf("%d\n",MAX(ans1,ans2));
}
return 0;
}

• 本文已收录于以下专栏：

## tarjan模板（缩点，求有向图强连通分量）

• martinue
• 2016年05月04日 15:53
• 1574

## scc缩点

• mirror58229
• 2017年09月14日 17:31
• 98

## hdoj 3836 Equivalent Sets 【tarjan 求SCC + 缩点】

﻿﻿ Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/...
• chenzhenyu123456
• 2015年07月18日 21:40
• 293

## 缩点

• mnlghttr
• 2013年09月19日 08:51
• 1143

## HDU3836--Equivalent Sets(强连通+缩点)

• u011639302
• 2014年01月23日 09:01
• 661

## 消息扩散（Tarjan算法缩点处理）

P2002 消息扩散 题目概述 给定一张有向图，不保证无自环与重边，信息从某几个节点出发，沿单向路传播，现在给出n个节点及其之间的道路，问至少需要在几个节点发布信息才能让这所有节点都得到信息。 ...
• Stockholm_Sun
• 2017年08月11日 10:33
• 216

## poj 1236 Network (SCC缩点)

• u014679804
• 2015年06月27日 10:49
• 319

## hdu3836 Equivalent Sets(缩点)

• hill_555
• 2013年07月31日 19:38
• 284

• qq_24451605
• 2015年07月15日 15:43
• 801

## POJ 2186【Tarjan算法(模板_缩点)】

//在一张有向无环图G，图G会包含很多环（环里面的点是等价的）， //当然可以把环缩成一个点（利用tarjan缩点）， //形成一棵树，题目要求是求除他以外的点都指向他，也就是只有一个叶子。 //因为...
• KEYboarderQQ
• 2016年05月15日 10:13
• 891

举报原因： 您举报文章：hdoj3836Equivalent Sets【scc +缩点】 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)