HDU3836 Equivalent Sets【有向图强连通分支+缩点】

探讨了如何使用最少步骤证明多个集合等价的问题,通过Tarjan算法寻找强连通分量,进而统计并确定所需的最少证明步骤。适用于竞赛编程中的集合等价证明题目。

Equivalent Sets

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


 

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

2011 Multi-University Training Contest 1 - Host by HNU

问题链接:HDU3836 Equivalent Sets

解题思路:此题与 HDU2767 Proving Equivalences 一样,只是输入格式有细微区别。

AC的C++程序:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>

using namespace std;

const int N=20005;

bool flag[N];
int dfn[N],low[N],index;
int in[N],out[N];//缩点后的新图各点的入度和出度
int belong[N];//记录原图个点所属的强连通分量的编号
int cnt;//强连通分量的个数
int n,m;

vector<int>g[N];
stack<int>s;

void Tarjan(int u)
{
	dfn[u]=low[u]=++index;
	s.push(u);
	flag[u]=true;
	for(int i=0;i<g[u].size();i++)
	{
		int v=g[u][i];
		if(!dfn[v])
		{
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(flag[v])
		  low[u]=min(low[u],dfn[v]);
	}
	if(dfn[u]==low[u])
	{
		cnt++;
		int v;
		do{
			v=s.top();
			s.pop();
			flag[v]=false;
			belong[v]=cnt;
		}while(v!=u);
	}
}

void solve()
{
	for(int i=0;i<=n;i++)
	  dfn[i]=low[i]=in[i]=out[i]=belong[i]=flag[i]=0;
	cnt=index=0;
	while(!s.empty()) s.pop();
	for(int i=1;i<=n;i++)
	  if(!dfn[i])
	    Tarjan(i);
	//统计缩点后各个节点的入度和出度
	for(int u=1;u<=n;u++)
	  for(int i=0;i<g[u].size();i++)
	  {
	  	int v=g[u][i];
	  	if(belong[u]!=belong[v])
	  	{
	  		out[belong[u]]++;
	  		in[belong[v]]++;
		}
	   } 
	if(cnt==1)//只有一个强连通分量,不用加边 
	{
		printf("0\n");
		return;
	}
	int num1=0,num2=0;//统计入度和出度为0的节点的个数 
	for(int i=1;i<=cnt;i++)
	{
		if(in[i]==0)
		  num1++;
		if(out[i]==0)
		  num2++;
	}
	printf("%d\n",max(num1,num2));//添加的边数为num1和num2的较大者 
}

int main()
{
	int a,b;
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=0;i<=n;i++)
		  g[i].clear();
		while(m--)
		{
			scanf("%d%d",&a,&b);
			g[a].push_back(b);
		}
		solve();
	}
	return 0;
}
 

 

下载代码方式:https://pan.quark.cn/s/a4b39357ea24 HTML大屏展示模板是一种用于设计具有视觉冲击力且内容充实的巨型显示屏应用的设计方案,其应用范围广泛,涵盖了数据分析、监控以及决策支持等多个领域。这些模板通常整合了HTML、CSS、JavaScript等多种技术,尤其借助ECharts等数据可视化工具以达成复杂数据的图形化呈现。以下是对相关技术细节的深入说明: 1. **可视化**:数据可视化是将抽象的数据转化为直观的图像或图表的技术手段。这种技术有助于迅速识别数据中的模式、发展趋势和异常情况,使得非专业背景的人员也能轻松理解复杂的数据信息。在大屏展示场景中,可视化通常包含折线图、柱状图、饼图、热力图、地图等多种图表形式。 2. **大数据**:大数据指的是规模庞大、增长迅速、种类多样且数据密度较低的数据集合。在HTML大屏展示中,大数据的应用旨在支持实时或近乎实时的决策制定,例如监控销售业绩、交通流量、能源消耗等关键性能指标。 3. **HTML**:超文本标记语言(HTML)构成了网页内容的基础结构,用于界定页面的布局和元素。在大屏展示模板中,HTML负责构建页面组件,例如标题、段落、图像以及图表容器等。 4. **CSS**:层叠样式表(CSS)用于调控网页的视觉风格和布局结构。在大屏模板设计中,CSS扮演着核心角色,确保设计的响应性、适应性和美观度,包括设定颜色、字体、间距、动画效果等。 5. **ECharts**:ECharts是由百度研发的一款开源JavaScript数据可视化库,能够支持多种图表类型,如折线图、柱状图、散图等,并提供了丰富的交互特性。在大屏展示中,ECharts能够助力生成动态且交互式的数据...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值