HDOJ--3836--Equivalent Sets(tarjan算法)//求连接几个SCC最少的边

原创 2015年11月21日 20:49:21

Equivalent Sets

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


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.
 
思路:利用tarjan算法求出SCC的数量,然后根据缩点后每个节点的入度出度情况来去求连接这几个SCC最少的边数。这里要利用到一个结论,连接几个SCC最少需要的边是缩点后几个节点的0入度数量和0出度数量中的最大值。详细见代码。
ac代码:
#include<stdio.h>
#include<string.h>
#include<stack>
#include<vector>
#include<algorithm>
#define INF 0x3f3f3f
#define MAXN 20000+10
using namespace std;
vector<int>mp[MAXN];//存储图 
vector<int>sccno[MAXN];//存储每个强连通分量;
vector<int>NEW[MAXN]; 
stack<int>q;//将遍历过得节点记录在栈里 
bool Instack[MAXN];//记录是否在栈里。 
int  In[MAXN],Out[MAXN];//记录入度,出度。	
int low[MAXN],dfn[MAXN],scc[MAXN];//sccno记录每个节点 属于哪个强连通分量 
int dfs_clock,scc_cnt; 
int n,m;
void get_map(){
	for(int i=1;i<=n;i++)
		mp[i].clear();
	for(int i=0;i<m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		mp[u].push_back(v);
	}
}
void tarjan(int u){
	int v;//下一个节点; 
	low[u]=dfn[u]=++dfs_clock;
	Instack[u]=true;
	q.push(u); 
		for(int j=0;j<mp[u].size();j++){//遍历U节点的每一条边。 
					v=mp[u][j];
			if(!dfn[v]){
				tarjan(v);
				low[u]=min(low[u],low[v]);//更新low数组 
			}
			else	if(Instack[v])
				low[u]=min(low[u],dfn[v]);//建立反向边。
		} 	 
	if(dfn[u]==low[u]){
		scc_cnt++;
		while(1){
			v=q.top();
			q.pop();
			scc[v]=scc_cnt;
			sccno[scc_cnt].push_back(v); 
			Instack[v]=false;
			if(u==v)
				break;
		}
	} 
}
void find_cut(){
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	memset(Instack,false,sizeof(Instack));
	dfs_clock=scc_cnt=0;
	for(int i=1;i<=n;i++)
		if(!dfn[i])
			tarjan(i);
}
void SCC(){
	memset(In,0,sizeof(In));
	memset(Out,0,sizeof(Out));
	for(int i=1;i<=scc_cnt;i++)
		NEW[i].clear();
	for(int i=1;i<=n;i++){
		for(int j=0;j<mp[i].size();j++){//遍历所有边,构建新图。
			 int u=scc[i];//找到这两个点是否是同一个强连通分量 
			 int v=scc[mp[i][j]];
			 if(u!=v) {//如果不是,构建新边。
			 NEW[u].push_back(v);
			 In[v]++;
			 Out[u]++; 
			 }	
		}
	}
}
void solve(){
	int sumin=0,sumout=0;
		if(scc_cnt==1){
			printf("0\n");
		}
		else{
			for(int i=1;i<=scc_cnt;i++){
				if(In[i]&&Out[i])
					continue;
				if(!In[i]) 
					sumin++;
				if(!Out[i])
					sumout++;
			}
				int ans=max(sumin,sumout);
				printf("%d\n",ans);
		}
}
int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		get_map();
		find_cut();
		SCC();
		solve(); 
	}
	
	return 0;
} 
自己终于算得上是稍微学会了一点强连通吧,也算是有点进步了。

版权声明:本文为小小呆原创文章,欲转载,请在后台勾搭本呆。

相关文章推荐

HDU 3836--Equivalent Sets【求有向图最少增加多少边使图强连通 && Scc缩点新建图】

Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Othe...
  • hpuhjh
  • hpuhjh
  • 2015年08月19日 21:27
  • 312

POJ 1236 Network of Schools HDU 3836 Equivalent Sets 强连通分量+缩点 tarjan or kosaraju

1,POJ 1236 有一些学校连接到一个计算机网络,这些学校之间达成了一个协议:每个学校维护着一个学校列表,它向学校列表中的学校发布软件。注意,如果学校B在学校A的列表中,则A不一定在B的列表中。...

HDU 3836 Equivalent Sets(强连通分量 Tarjan缩点)

Tarjan求强连通分量详解在前一篇文章 把一个有向图变为强连通分量至少要加几条边? Tarjan缩点后,设a为入度为0的点数,b为出度为0的点数,答案max(a,b)。 注意:如果图本...

hdu 3836 Equivalent Sets 强联通 tarjan缩点

求强连通分量,然后统计每一个分量的入度和初度 这两个量中较大的那一个就是答案了...

HDOJ/HDU 3836 Equivalent Sets

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3836 Problem DescriptionTo prove two sets A and B are...

Equivalent Sets 【至少加几边使图为强联通】+【 scc +缩点】

To prove two sets A and B are equivalent, we can first prove A is a subset of B, and then prove B is...

hdu 3836 Equivalent Sets(强连通分量--加边)

Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Other...

HDU3836Equivalent Sets(强连通+加边构成强连通)

题意:至少加几条边构成强连通, 和上一题一样 #include #include #include #include #include #include #include #include #incl...

hdoj 3062 Party 【2-sat入门 :布尔表达式建边 有向图tarjan求SCC】 【离散没学好是硬伤】

Party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su...

HDU 3836 — Equivalent Sets

原题:http://acm.hdu.edu.cn/showproblem.php?pid=3836 题意:给出一个有向图,问最少加几条边使得该图强连通; 思路:先求出所有的强连通分量,计算新图中入...
  • L__emon
  • L__emon
  • 2015年05月01日 23:10
  • 192
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDOJ--3836--Equivalent Sets(tarjan算法)//求连接几个SCC最少的边
举报原因:
原因补充:

(最多只允许输入30个字)