码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 3836 Equivalent Sets(tarjan)

时间:2015-08-17 21:43:43      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:

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
 

 把tarjan复习了一遍

1 题目描述:将题目中的集合转换为顶点,A集合是B集合的子集,转换为一条有向边<A,B>,即题目给我们一个有向图,问最少需要添加多少条边使之成为强连通图。 
2 解题思路:通过tarjan算法找出图中的所有强连通分支,并将每一个强连通分支缩成一个点(因为强连通分量本身已经满足两两互相可达)。 
3 要使缩点后的图成为强连通图,每个顶点最少要有一个入度和一个出度,一条边又提供一个出度和一个入度。 
4 所以可以通过统计没有入度的顶点数 noInDegree 和 没有出度的顶点数 noOutDegree。 
5 所需要添加的边数就是noInDegree和noOutDegree中的最大值。 

 

 

技术分享
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<stack>
  5 #include<vector>
  6 using namespace std;
  7 #define N 20006
  8 #define inf 1<<26
  9 int n,m;
 10 struct Node
 11 {
 12     int from;
 13     int to;
 14     int next;
 15 }edge[N<<6];
 16 int tot;//表示边数,边的编号
 17 int head[N];
 18 int vis[N];
 19 int tt;
 20 int scc;
 21 stack<int>s;
 22 int dfn[N],low[N];
 23 int col[N];
 24 
 25 void init()//初始化
 26 {
 27     tt=0;
 28     tot=0;
 29     memset(head,-1,sizeof(head));
 30     memset(dfn,-1,sizeof(dfn));
 31     memset(low,0,sizeof(low));
 32     memset(vis,0,sizeof(vis));
 33     memset(col,0,sizeof(col));
 34 }
 35 
 36 void add(int s,int u)//邻接矩阵函数
 37 {
 38     edge[tot].from=s;
 39     edge[tot].to=u;
 40     edge[tot].next=head[s];
 41     head[s]=tot++;
 42 }
 43 
 44 void tarjan(int u)//tarjan算法找出图中的所有强连通分支
 45 {
 46     dfn[u] = low[u]= ++tt;
 47     vis[u]=1;
 48     s.push(u);
 49     int cnt=0;
 50     for(int i=head[u];i!=-1;i=edge[i].next)
 51     {
 52         int v=edge[i].to;
 53         if(dfn[v]==-1)
 54         {
 55         //    sum++;
 56             tarjan(v);
 57             low[u]=min(low[u],low[v]);
 58         }
 59         else if(vis[v]==1)
 60           low[u]=min(low[u],dfn[v]);
 61     }
 62     if(dfn[u]==low[u])
 63     {
 64         int x;
 65         scc++;
 66         do{
 67             x=s.top();
 68             s.pop();
 69             col[x]=scc;
 70             vis[x]=0;
 71         }while(x!=u);
 72     }
 73 }
 74 
 75 int main()
 76 {
 77     while(scanf("%d%d",&n,&m)==2 && n+m)
 78     {
 79         
 80         init();
 81         
 82         scc=0;//scc表示强连通分量的个数
 83         while(m--)
 84         {
 85             int a,b;
 86             scanf("%d%d",&a,&b);
 87             add(a,b);//构造邻接矩阵
 88         }
 89         for(int i=1;i<=n;i++)
 90         {
 91             if(dfn[i]==-1)
 92             {
 93                 tarjan(i);
 94             }
 95         }
 96        //printf("%d\n",scc);
 97        
 98        
 99        int inde[N];
100        int outde[N];
101        memset(inde,0,sizeof(inde));
102        memset(outde,0,sizeof(outde));
103        for(int i=0;i<tot;i++)
104        {
105             int a=edge[i].from;
106             int b=edge[i].to;
107             if(col[a]!=col[b])
108             {
109                  inde[col[b]]++;
110                  outde[col[a]]++;
111            }
112        }
113        
114        int ans1=0;
115        int ans2=0;
116        for(int i=1;i<=scc;i++)
117        {
118            if(inde[i]==0)
119            {
120                   ans1++;
121            }
122            if(outde[i]==0)
123            {
124                  ans2++;
125            }
126        }
127        if(scc==1)
128        {
129            printf("0\n");
130            continue;
131        }
132        printf("%d\n",max(ans1,ans2));
133        
134     }
135     return 0;
136 }
View Code

 

hdu 3836 Equivalent Sets(tarjan)

标签:

原文地址:http://www.cnblogs.com/UniqueColor/p/4737731.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!