hdu 3836 Equivalent Sets(tarjan+缩点)
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.
The input file contains multiple test cases, in each case, the first line contains two integers N <= and M <= .
Next M lines, each line contains two integers X, Y, means set X in a subset of set Y.
For each case, output a single integer: the minimum steps needed.
Case 2: First prove set 2 is a subset of set 1 and then prove set 3 is a subset of set 1.
把tarjan复习了一遍
题目描述:将题目中的集合转换为顶点,A集合是B集合的子集,转换为一条有向边<A,B>,即题目给我们一个有向图,问最少需要添加多少条边使之成为强连通图。
解题思路:通过tarjan算法找出图中的所有强连通分支,并将每一个强连通分支缩成一个点(因为强连通分量本身已经满足两两互相可达)。
要使缩点后的图成为强连通图,每个顶点最少要有一个入度和一个出度,一条边又提供一个出度和一个入度。
所以可以通过统计没有入度的顶点数 noInDegree 和 没有出度的顶点数 noOutDegree。
所需要添加的边数就是noInDegree和noOutDegree中的最大值。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<vector>
using namespace std;
#define N 20006
#define inf 1<<26
int n,m;
struct Node
{
int from;
int to;
int next;
}edge[N<<];
int tot;//表示边数,边的编号
int head[N];
int vis[N];
int tt;
int scc;
stack<int>s;
int dfn[N],low[N];
int col[N]; void init()//初始化
{
tt=;
tot=;
memset(head,-,sizeof(head));
memset(dfn,-,sizeof(dfn));
memset(low,,sizeof(low));
memset(vis,,sizeof(vis));
memset(col,,sizeof(col));
} void add(int s,int u)//邻接矩阵函数
{
edge[tot].from=s;
edge[tot].to=u;
edge[tot].next=head[s];
head[s]=tot++;
} void tarjan(int u)//tarjan算法找出图中的所有强连通分支
{
dfn[u] = low[u]= ++tt;
vis[u]=;
s.push(u);
int cnt=;
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if(dfn[v]==-)
{
// sum++;
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]==)
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
int x;
scc++;
do{
x=s.top();
s.pop();
col[x]=scc;
vis[x]=;
}while(x!=u);
}
} int main()
{
while(scanf("%d%d",&n,&m)== && n+m)
{ init(); scc=;//scc表示强连通分量的个数
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);//构造邻接矩阵
}
for(int i=;i<=n;i++)
{
if(dfn[i]==-)
{
tarjan(i);
}
}
//printf("%d\n",scc); int inde[N];
int outde[N];
memset(inde,,sizeof(inde));
memset(outde,,sizeof(outde));
for(int i=;i<tot;i++)
{
int a=edge[i].from;
int b=edge[i].to;
if(col[a]!=col[b])
{
inde[col[b]]++;
outde[col[a]]++;
}
} int ans1=;
int ans2=;
for(int i=;i<=scc;i++)
{
if(inde[i]==)
{
ans1++;
}
if(outde[i]==)
{
ans2++;
}
}
if(scc==)
{
printf("0\n");
continue;
}
printf("%d\n",max(ans1,ans2)); }
return ;
}
hdu 3836 Equivalent Sets(tarjan+缩点)的更多相关文章
- hdu 3836 Equivalent Sets trajan缩点
Equivalent Sets Time Limit: 12000/4000 MS (Java/Others) Memory Limit: 104857/104857 K (Java/Other ...
- [tarjan] hdu 3836 Equivalent Sets
主题链接: http://acm.hdu.edu.cn/showproblem.php? pid=3836 Equivalent Sets Time Limit: 12000/4000 MS (Jav ...
- hdu 3836 Equivalent Sets
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3836 Equivalent Sets Description To prove two sets A ...
- hdu 3836 Equivalent Sets(强连通分量--加边)
Equivalent Sets Time Limit: 12000/4000 MS (Java/Others) Memory Limit: 104857/104857 K (Java/Other ...
- hdu——3836 Equivalent Sets
Equivalent Sets Time Limit: 12000/4000 MS (Java/Others) Memory Limit: 104857/104857 K (Java/Other ...
- hdu - 3836 Equivalent Sets(强连通)
http://acm.hdu.edu.cn/showproblem.php?pid=3836 判断至少需要加几条边才能使图变成强连通 把图缩点之后统计入度为0的点和出度为0的点,然后两者中的最大值就是 ...
- HDU3836 Equivalent Sets (Tarjan缩点+贪心)
题意: 给你一张有向图,问你最少加多少条边这张图强连通 思路: 缩点之后,如果不为1个点,答案为出度为0与入度为0的点的数量的最大值 代码: #include<iostream> #inc ...
- HDU - 3836 Equivalent Sets (强连通分量+DAG)
题目大意:给出N个点,M条边.要求你加入最少的边,使得这个图变成强连通分量 解题思路:先找出全部的强连通分量和桥,将强连通分量缩点.桥作为连线,就形成了DAG了 这题被坑了.用了G++交的,结果一直R ...
- hdoj 3836 Equivalent Sets【scc&&缩点】【求最少加多少条边使图强连通】
Equivalent Sets Time Limit: 12000/4000 MS (Java/Others) Memory Limit: 104857/104857 K (Java/Other ...
随机推荐
- HtmlParser 2.0 中文乱码问题
对于HTMLParser 2.0 工具包我们需要修改其中的Page.java文件使其适用中文的html文件分析. 主要是把protected static final String DEFAULT_C ...
- 类型兼容原则(C++)
类型兼容原则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代. 通过公有继承,派生类得到了基类中除构造函数.析构函数之外的所有成员.这样,公有派生类实际具备了基类的所有功能,凡是基类能解 ...
- 10个热门IT证书
MCP (微软专家认证) CCNA (思科认证网络支持工程师) MCPD (微软认证开发专家) SCJP (SUN认证Java程序员) CISSP (信息系统安全认证专家) CompTIA A+认证 ...
- 让你的java开发变得如此 Smart
http://my.oschina.net/huangyong/blog/196408
- KindEditor简单的Demo使用
一般的做网站后台都会用到富文本编辑器,网上也有很多优秀的富文本编辑器,这里是开源中国的富文本编辑器推荐:http://www.oschina.net/project/tag/172/wysiwyg 我 ...
- [编辑中] 免费的Internet流量发生器 | Free Internet Traffic Generators
流量发生器 (Traffic Generator) 是用来检测网络性能,进行网络相关研究的一个很重要的工具.大家可能用过Iperf或者IxChariot,前者是类UNIX环境下的一个免费.开源的网络性 ...
- Windows下用Caffe跑自己的数据(遥感影像)
1 前言 Caffe对于像我这样的初学者来说是一款非常容易上手的深度学习框架.关于用Caffe跑自己的数据这样的博客已经非常多,感谢前辈们为我们提供的这么好的学习资源.这里我主要结合我所在的行业,说下 ...
- Python 日期和时间(转)
Python 日期和时间 Python程序能用很多方式处理日期和时间.转换日期格式是一个常见的例行琐事.Python有一个 time 和 calendar 模组可以帮忙. 什么是Tick? 时间间隔是 ...
- Android Activity 分类
在安卓系统中,Activity 按照优先级可以分为三种: 1. 前台Activity,是指正在和用户进行交互的Activity,优先级最高: 2.可见但非前台Activity,是指可见但无法与用户进行 ...
- 序列化和持久化 merge方法和saveOrUpdate方法
merge方法和saveOrUpdate方法的区别 merge方法是把我们提供的对象转变为托管状态的对象:而saveOrUpdate则是把我们提供的对象变成一个持久化对象:说的通俗一点就是:saveO ...