• hdu 3836 Equivalent Sets(tarjan+缩点)


    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
    ",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
    ");
    130            continue;
    131        }
    132        printf("%d
    ",max(ans1,ans2));
    133        
    134     }
    135     return 0;
    136 }
    View Code
  • 相关阅读:
    Gatling 条件判断
    Gatling脚本编写技巧篇(二)
    Gatling脚本编写技巧篇(一)
    性能测试-pidstat 问题定位分析
    REACT——无状态组件
    REACT——react-transition-group 实现动画
    REACT——生命周期函数
    REACT——ref的使用
    REACT——虚拟DOM
    REACT——Props、status与render
  • 原文地址:https://www.cnblogs.com/UniqueColor/p/4737731.html
Copyright © 2020-2023  润新知