hdu 3836 Equivalent Sets(tarjan+缩点)
2015-08-17 20:58
387 查看
[align=left]Problem Description[/align]
[align=left]Input[/align]
[align=left]Output[/align]
[align=left]Sample Input[/align]
[align=left]Sample Output[/align]
Hint
Case 2: First prove set 2 is a subset of set 1 and then prove set 3 is a subset of set 1.
[align=left]Source[/align]
2011 Multi-University Training Contest 1 - Host by HNU
把tarjan复习了一遍
View Code
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.
[align=left]Input[/align]
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.
[align=left]Output[/align]
For each case, output a single integer: the minimum steps needed.
[align=left]Sample Input[/align]
4 0 3 2 1 2 1 3
[align=left]Sample Output[/align]
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.
[align=left]Source[/align]
2011 Multi-University Training Contest 1 - Host by HNU
把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<<6]; int tot;//表示边数,边的编号 int head ; int vis ; int tt; int scc; stack<int>s; int dfn ,low ; int col ; void init()//初始化 { tt=0; tot=0; memset(head,-1,sizeof(head)); memset(dfn,-1,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(col,0,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]=1; s.push(u); int cnt=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(dfn[v]==-1) { // sum++; tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]==1) 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]=0; }while(x!=u); } } int main() { while(scanf("%d%d",&n,&m)==2 && n+m) { init(); scc=0;//scc表示强连通分量的个数 while(m--) { int a,b; scanf("%d%d",&a,&b); add(a,b);//构造邻接矩阵 } for(int i=1;i<=n;i++) { if(dfn[i]==-1) { tarjan(i); } } //printf("%d\n",scc); int inde ; int outde ; memset(inde,0,sizeof(inde)); memset(outde,0,sizeof(outde)); for(int i=0;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=0; int ans2=0; for(int i=1;i<=scc;i++) { if(inde[i]==0) { ans1++; } if(outde[i]==0) { ans2++; } } if(scc==1) { printf("0\n"); continue; } printf("%d\n",max(ans1,ans2)); } return 0; }
View Code
相关文章推荐
- UITableView之上拉刷新
- IOS UITableView 图片文字重叠问题
- POJ 题目3080 Blue Jeans(KMP+暴力)
- Powerbuilder 连接字符串各个参数 Database parameters and supported database interfaces
- UIView添加手势 然后UITableView 添加进这个View 导致UITableView 的单元格点击事件无效
- uva 1342 - That Nice Euler Circuit(欧拉定理)
- 1085. Perfect Sequence (25)
- Squence 设置主键自动增长,设置起始值、步长
- Quick Reference: git 的.gitignore文件
- [POJ2478]Farey Sequence
- UIMenuController 的使用指南
- HDU2227(Find the nondecreasing subsequences)
- 对UITableView的一些设置
- Light OJ 1188 Fast Queries(分块暴力)
- POJ3038(Blue Jeans)
- QuickSort 快速排序 基于伪代码实现
- easyui 快速开发整理
- iOS开发-Day25-UIView
- SPOJ 题目375 Query on a tree(link cut tree边权更新,求两点最大值)
- requireJs杂项