zoukankan      html  css  js  c++  java
  • Equivalent Sets HDU

    题意:

      给一些集合 要求证明所有集合是相同的

      证明方法是,如果$A∈B$,$B∈A$那么$A=B$成立

      每一次证明可以得出一个$X∈Y$

      现在已经证明一些$A∈B$成立

      求,最少再证明多少次,就可以完成要求

    分析

      其实就等价于给一个有向图,问你再加入多少个边可以使得图变为强连通图

      给一个图论经典结论:

      "对于一个有向无环图(DAG),若想让它成为强连通图,至少需要添加$max(a,b)$条边 $a$为入度为0的点的数量,$b$为出度为0的点的数量"

      而对于一个有向图,其每个强连通分量都互相可达,也就是只要到达任意一个点,即可到达内部所有的点

      现在,只要对于强连通分量进行缩点,再新图中统计出入度数即可得到答案

      *注意,如果强连通分量只有1个,答案应该是0而不是1

    #include <bits/stdc++.h>
    #define ll long long
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define pp pair<int,int>
    #define rep(ii,a,b) for(int ii=a;ii<=b;ii++)
    #define per(ii,a,b) for(int ii=a;ii>=b;ii--)
    #define show(x) cout<<#x<<"="<<x<<endl
    #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
    #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
    #define showa(a,b) cout<<#a<<'['<<#b<<"]="<<a[b]<<endl
    using namespace std;
    const int maxn=1e5+10;
    const int maxm=1e6+10;
    const int INF=0x3f3f3f3f;
    int casn,n,m,k;
    int stk[maxn],top,cnt,dfn[maxn],low[maxn],numc,belong[maxn],vis[maxn];
    struct node {int to,cost,next;}e[maxm];int head[maxn],nume;
    void add(int a,int b,int c=1){e[++nume]=(node){b,c,head[a]};head[a]=nume;}
    void tdfs(int now){
    	dfn[now]=low[now]=++cnt;
    	stk[top++]=now;
    	vis[now]=1;
    	for(int i=head[now];i;i=e[i].next){
    		int to=e[i].to;
    		if(!dfn[to]){tdfs(to);low[now]=min(low[now],low[to]);}
    		else if(vis[to]) low[now]=min(low[now],dfn[to]);
    	}
    	if(low[now]==dfn[now]){
    		numc++;
    		int to;
    		do{
    			to=stk[--top];
    			belong[to]=numc;
    			vis[to]=0;
    		}while(to!=now);
    	}
    }
    void tarjan(int numv=n){
    	for(int i=1;i<=numv;i++){
    		if(!dfn[i]) tdfs(i);
    	}
    }
    void ginit(){
    	nume=top=numc=cnt=0;
    	memset(head,0,sizeof head);
    	memset(dfn,0,sizeof dfn);
    }
    int din[maxn],dout[maxn];
    
    int main(){
    //#define test
    #ifdef test
      freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    #endif
    
      while(cin>>n>>m){
        if(m==0) {
          cout<<n<<endl;
          continue;
        }
        ginit();
        memset(din,0,sizeof din);
        memset(dout,0,sizeof dout);
        for(int i=0;i<m;i++){
          int a,b;
          cin>>a>>b;
          add(a,b);
        }
        tarjan();
        for(int i=1;i<=n;i++){
          for(int j=head[i];j;j=e[j].next){
          	if(belong[i]==belong[e[j].to])continue;
            dout[belong[i]]++;
            din[belong[e[j].to]]++;
          }
        }
        int a=0,b=0;
        for(int i=1;i<=numc;i++){
          if(din[i]==0)a++;
          if(dout[i]==0)b++;
        }
        if(numc==1) a=b=0;
        cout<<max(a,b)<<endl;
      }
    
    #ifdef test
      fclose(stdin);fclose(stdout);system("out.txt");
    #endif
      return 0;
    }
    

      

  • 相关阅读:
    看代码写程序
    NP
    一道神题
    找平方数
    凝视
    排队打水
    时间计算
    git客户端下载地址
    iOS GCD
    UIView 和 CALayer的那点事
  • 原文地址:https://www.cnblogs.com/nervendnig/p/9124280.html
Copyright © 2011-2022 走看看