zoukankan      html  css  js  c++  java
  • 两种代码风格解决强连通分量解决加多少条边使整个图连通&多少个点可以到达所有点

    使用Tarjan进行缩点,得到一个SCC图、
    这个图有多少个入度为0的,多少个出度为0的。

    假设有n个入度为0,m个出度为0

    那么需要给n个点才能传遍所有点,需要加max(n,m)条边才能使整个图变成强连通分量

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<vector>
    #include<set>
    #include<stack>
    #include<string>
    
    //#include<bits/stdc++.h>
    using namespace std;
    const int maxn=110;
    
    struct Node{
        int to,next;
    }edge1[maxn*100],edge2[maxn*100];
    
    int head1[maxn],head2[maxn];
    int mark1[maxn],mark2[maxn];
    int tot1,tot2;
    int num,setNum[maxn];
    int cnt1,cnt2,st[maxn],belong[maxn];
    struct Edge{
        int l,r;
    }e[maxn*100];
    
    void add(int a,int b)
    {
        edge1[tot1].to=b;edge1[tot1].next=head1[a];head1[a]=tot1++;
        edge2[tot2].to=a;edge2[tot2].next=head2[b];head2[b]=tot2++;
    }
    
    void DFS1(int x)
    {
        mark1[x]=1;
        for(int i=head1[x];i!=-1;i=edge1[i].next)
            if(!mark1[edge1[i].to])DFS1(edge1[i].to);
        st[cnt1++]=x;
    }
    
    void DFS2(int x)
    {
        mark2[x]=1;
        num++;
        belong[x]=cnt2;
        for(int i=head2[x];i!=-1;i=edge2[i].next)
            if(!mark2[edge2[i].to])DFS2(edge2[i].to);
    }
    
    int main()
    {
        int n,m;
        while(scanf("%d",&n)!=EOF)
        {
            int w,v;
            tot1=tot2=1;
            for(int i=1;i<=n;i++)
            {
                head1[i]=head2[i]=-1;
                mark1[i]=mark2[i]=0;
            }
            m=0;
            for(w=1;w<=n;w++)
            {
                while(scanf("%d",&v)&&v){
                    m++;e[m].l=w,e[m].r=v;
                    add(w,v);
                }
            }
            cnt1=cnt2=1;
            for(int i=1;i<=n;i++){
                if(!mark1[i])DFS1(i);
            }
            for(int i=cnt1-1;i>=1;i--)
            {
                if(!mark2[st[i]])
                {
                    num=0;
                    DFS2(st[i]);
                    setNum[cnt2++]=num;
                }
            }
            int out[maxn],in[maxn];//计算出度和入度
            memset(out,0,sizeof(out));
            memset(in,0,sizeof(in));
            for(int i=1;i<=m;i++)
            {
                if(belong[e[i].l]!=belong[e[i].r])
                {
                    out[belong[e[i].l]]++;
                    in[belong[e[i].r]]++;
                }
            }
            int res1=0;//出度为0的个数
            int res2=0;//入度为0的个数
            for(int i=1;i<cnt2;i++)
            {
                if(!out[i]) res1++;
                if(!in[i])  res2++;
            }
            //下面这个是关键,整张图就一个连通分量时,输出0,1.WR了好几次呢
            if(cnt2==2) {printf("1
    0
    ");continue;}
            printf("%d
    ",res2);
            printf("%d
    ",res1>res2?res1:res2);
        }
        return 0;
    }
    

    第二种Tarjan求解!!

    #include <algorithm>  
        #include <iostream>  
        #include <sstream>  
        #include <cstring>  
        #include <cstdlib>  
        #include <string>  
        #include <vector>  
        #include <cstdio>  
        #include <stack>  
        #include <cmath>  
        #include <queue>  
        #include <map>  
        #include <set>  
        using namespace std;  
        #define N 105  
    
        vector<int> e[N];  
        int dfn[N], low[N],stap[N], stop,belong[N],outdeg[N],indeg[N],dindex, cnt;  
        bool instack[N];  
        int n, m;  
    
        void tarjan(int x){  
            int y = 0;  
            dfn[x]=low[x]=++dindex;  
            instack[x]=true;  
            stap[++stop]=x;  
            for (int i=0; i<e[x].size(); i++) {  
                y=e[x][i];  
                if (!dfn[y]) {  
                    tarjan(y);  
                    if (low[y]<low[x]) {  
                        low[x]=low[y];  
                    }  
                }  
                else if (instack[y]&&dfn[y]<low[x]){  
                    low[x]=dfn[y];  
                }  
            }  
            if (dfn[x]==low[x]) {  
                cnt++;  
                while (y!=x) {  
                    y=stap[stop--];  
                    instack[y]=false;  
                    belong[y]=cnt;  
                }  
            }  
        }  
    
        void solve(){  
            stop=dindex=cnt=0;  
            memset(dfn, 0, sizeof(dfn));  
            memset(instack, 0, sizeof(instack));  
            memset(outdeg, 0, sizeof(outdeg));  
            memset(indeg, 0, sizeof(indeg));  
            for (int i=1; i<=n; i++) {  
                if (!dfn[i]) {  
                    tarjan(i);  
                }  
            }  
        }  
    
        int main(){  
            int temp;  
            while (~scanf("%d", &n)) {  
                for (int i=1; i<=n; ++i) {  
                    e[i].clear();  
                }  
                for (int i=1; i<=n; i++) {  
                    while (scanf("%d",&temp)) {  
                        if (temp==0) {  
                            break;  
                        }  
                        e[i].push_back(temp);  
                    }  
                }  
                solve();  
                for (int i=1; i<=n; i++) {  
                    int size=e[i].size();  
                    for (int j=0; j<size; j++) {  
                        if (belong[i]!=belong[e[i][j]]) {  
                            outdeg[belong[i]]++;  
                            indeg[belong[e[i][j]]]++;  
                        }  
                    }  
                }  
                int sumout=0,sumin=0;  
                for (int i=1; i<=cnt; i++) {  
                    if (outdeg[i]==0) {  
                        sumout++;  
                    }  
                    if (indeg[i]==0) {  
                        sumin++;  
                    }  
                }  
                if (cnt==1) {  
                    printf("1
    0
    ");  
                }  
                else  
                printf("%d
    %d
    ",sumin,max(sumin,sumout));  
    
            }  
            return 0;  
        }  
  • 相关阅读:
    Logistic回归
    朴素贝叶斯
    决策树
    K-邻近(KNN)算法
    快速排序
    归并排序
    希尔排序
    插入排序
    选择排序
    浅谈系统服务分发
  • 原文地址:https://www.cnblogs.com/wlxtuacm/p/5712276.html
Copyright © 2011-2022 走看看