zoukankan      html  css  js  c++  java
  • HDU3836 Equivalent Sets (Tarjan缩点+贪心)

    题意:

    给你一张有向图,问你最少加多少条边这张图强连通

    思路:

    缩点之后,如果不为1个点,答案为出度为0与入度为0的点的数量的最大值

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    //#include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
    #include<unordered_map>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 1e9+7;
    const int maxn = 5e4+100;
    const int maxm = 2e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    vector<int>g[maxn];
    int f[maxn];
    int color[maxn],dfn[maxn],low[maxn],stack[maxn],vis[maxn],cnt[maxn];
    int in[maxn],out[maxn];
    int top,n,m,sum,ans;
    int deep = 0;
    void tarjan(int u){
        dfn[u]=++deep;
        low[u]=deep;
        vis[u]=1;
        stack[++top]=u;
        int sz=g[u].size();
        for(int i=0;i<sz;i++){
            int v=g[u][i];
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else{
                if(vis[v]){
                    low[u]=min(low[u],low[v]);
                }
            }
        }
        if(dfn[u]==low[u]){
            color[u]=++sum;
            vis[u]=0;
            while(stack[top]!=u){
                color[stack[top]]=sum;
                vis[stack[top--]]=0;
            }
            top--;
        }
        return;
    }
    PI edge[maxn];
    vector<int>v[maxn];
    int find(int x){
        return f[x]==x?x:f[x]=find(f[x]);
    }
    void dfs(int x, int fa){
        if(x!=fa){
            int t1 = find(x);
            int t2 = find(fa);
            f[t1]=t2;
        }
        if(v[x].size()==0&&x!=fa&&vis[x]==0){vis[x]=1;ans++;}
        for(int i = 0; i <(int)v[x].size(); i++){
            int y = v[x][i];
            dfs(y,fa);
        }
    }
    int main() {
        while(~scanf("%d %d", &n, &m)){
            deep=0;
            top=ans=sum=0;
            for(int i = 1; i <= n; i++){
                f[i]=i;
                color[i]=low[i]=dfn[i]=stack[i]=vis[i]=cnt[i]=0;
                g[i].clear();
                v[i].clear();in[i]=out[i]=0;
            }
            for(int i = 1; i <= m; i++){
                int x,y;
                scanf("%d %d", &x, &y);
                edge[i] = make_pair(x,y);
                g[x].pb(y);
            }
            for(int i = 1; i <= n; i++){
                if(!dfn[i])tarjan(i);
            }
            /*for(int i = 1; i <= n; i++){
                printf("--%d %d %d
    ",i,color[i],low[i]);
            }*/
            //suo dian
            for(int i = 1; i <= n; i++)vis[i]=0;
            for(int i = 1; i <= m; i++){
                int x = edge[i].fst;
                int y = edge[i].sc;
                x = color[x];
                y = color[y];
                if(x!=y){
                    v[x].pb(y);
                    in[y]++;
                    out[x]++;
                }
            }
            int In=0;
            int Ou=0;
            for(int i = 1; i <= sum; i++){
                if(in[i]==0)In++;
                if(out[i]==0)Ou++;
            }
            int ans = max(In,Ou);
            if(ans==1)ans--;
            printf("%d
    ",ans);
    
        }
        return 0;
    }
    /*
    4 3
    1 2
    2 3
    4 3
    
    4 3
    1 2
    2 3
    3 4
    
    8 6
    1 2
    1 3
    1 5
    3 4
    3 6
    6 7
    
    6 5
    1 2
    2 3
    3 1
    3 5
    1 4
    
    2 2 
    1 2 
    2 1
    
    3 3
    1 2
    2 3
    1 3
    
    7 6
    1 2
    2 3
    1 3
    4 5
    4 6
    4 7
    
    4 5
    1 2
    1 3
    1 4
    2 3
    3 4
    
    4 5
    1 2
    1 3
    1 4
    2 3
    4 3
    
    3 1
    1 2
     */
  • 相关阅读:
    你不知道的多重循环的事情
    【浅墨Unity3D Shader编程】之三 光之城堡篇:子着色器、通道与标签的写法 &amp; 纹理混合
    ssh 远程登陆指定port
    GMT和CST的转换
    Swift新手教程系列5-函数+selector在swift中的使用方法
    Mac OS X 10.10, Eclipse+ADT真机调试代码时,Device Chooser中不显示真机的解决方式
    android studio 0.8.1使用和遇到问题解决
    C语言之函数调用17—递归法之中的一个般函数的调用(2)
    C语言之基本算法25—牛顿迭代法求方程近似根
    FineUI之使用SQL脚本从数据库表中生成对应的输入控件
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10982018.html
Copyright © 2011-2022 走看看