zoukankan      html  css  js  c++  java
  • UVALive4287 hdu2767 hdu3836 强连通

    题意:有多个命题,需要证明他们可以互相推出,现在已经有一些证明关系即 A 可以证明 B,问至少还需要多少证明关系。

    首先,如果某几个命题证明关系可以成环,那么这些命题必然可以相互证明,只要沿着环的边走就能到达其他命题,所以首先是需要强连通缩点,之后对于一个无环图,我们发现如果一个强连通分量它无出度,那么它就不能证明其他任何命题,如果它无入度,那么它就不能由任何命题证明,那么我们就需要消除这些入度或出度为0的点,其实只需要将入度为 0 的点建边指向出度为 0 的点,然后剩下多余的,入度为 0 则随意向其他点出边,出度为 0 则随意让其他点向它建边,因此所需要建的边数就是入度为 0 点数和出度为 0 点数的最大值。如果一开始图就只剩一个强连通分量,那么虽然它的入度出度都为 0 ,但已经不需要加边。

    UVALive4287、hdu2767

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stack>
     4 #include<queue>
     5 using namespace std;
     6 
     7 const int maxn=2e4+5;
     8 const int maxm=5e4+5;
     9 
    10 int head[maxn],point[maxm],nxt[maxm],size;
    11 int n,t,scccnt;
    12 int stx[maxn],low[maxn],scc[maxn],id[maxn],od[maxn],numi,numo;
    13 stack<int>S;
    14 
    15 int min(int a,int b){return a<b?a:b;}
    16 int max(int a,int b){return a>b?a:b;}
    17 
    18 void init(){
    19     memset(head,-1,sizeof(head));
    20     size=0;
    21 }
    22 
    23 void add(int a,int b){
    24     point[size]=b;
    25     nxt[size]=head[a];
    26     head[a]=size++;
    27 }
    28 
    29 void dfs(int s){
    30     stx[s]=low[s]=++t;
    31     S.push(s);
    32     for(int i=head[s];~i;i=nxt[i]){
    33         int j=point[i];
    34         if(!stx[j]){
    35             dfs(j);
    36             low[s]=min(low[s],low[j]);
    37         }
    38         else if(!scc[j]){
    39             low[s]=min(low[s],stx[j]);
    40         }
    41     }
    42     if(low[s]==stx[s]){
    43         scccnt++;
    44         while(1){
    45             int u=S.top();
    46             S.pop();
    47             scc[u]=scccnt;
    48             if(s==u)break;
    49         }
    50     }
    51 }
    52 
    53 void setscc(){
    54     memset(stx,0,sizeof(stx));
    55     memset(scc,0,sizeof(scc));
    56     memset(id,0,sizeof(id));
    57     memset(od,0,sizeof(od));
    58     numi=numo=t=scccnt=0;
    59     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
    60     if(scccnt!=1){
    61         for(int i=1;i<=n;++i){
    62             for(int j=head[i];~j;j=nxt[j]){
    63                 int k=point[j];
    64                 if(scc[i]!=scc[k]){
    65                     id[scc[i]]++;
    66                     od[scc[k]]++;
    67                     if(id[scc[i]]==1)numi++;
    68                     if(od[scc[k]]==1)numo++;
    69                 }
    70             }
    71         }
    72         numi=scccnt-numi;
    73         numo=scccnt-numo;
    74     }
    75 }
    76 
    77 int main(){
    78     int T;
    79     scanf("%d",&T);
    80     while(T--){
    81         int m;
    82         scanf("%d%d",&n,&m);
    83         init();
    84         while(m--){
    85             int a,b;
    86             scanf("%d%d",&a,&b);
    87             add(a,b);
    88         }
    89         setscc();
    90         printf("%d
    ",max(numi,numo));
    91     }
    92     return 0;
    93 }
    94         
    View Code

    hdu3836

    恩,就是改下输入

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stack>
     4 #include<queue>
     5 using namespace std;
     6 
     7 const int maxn=2e4+5;
     8 const int maxm=5e4+5;
     9 
    10 int head[maxn],point[maxm],nxt[maxm],size;
    11 int n,t,scccnt;
    12 int stx[maxn],low[maxn],scc[maxn],id[maxn],od[maxn],numi,numo;
    13 stack<int>S;
    14 
    15 int min(int a,int b){return a<b?a:b;}
    16 int max(int a,int b){return a>b?a:b;}
    17 
    18 void init(){
    19     memset(head,-1,sizeof(head));
    20     size=0;
    21 }
    22 
    23 void add(int a,int b){
    24     point[size]=b;
    25     nxt[size]=head[a];
    26     head[a]=size++;
    27 }
    28 
    29 void dfs(int s){
    30     stx[s]=low[s]=++t;
    31     S.push(s);
    32     for(int i=head[s];~i;i=nxt[i]){
    33         int j=point[i];
    34         if(!stx[j]){
    35             dfs(j);
    36             low[s]=min(low[s],low[j]);
    37         }
    38         else if(!scc[j]){
    39             low[s]=min(low[s],stx[j]);
    40         }
    41     }
    42     if(low[s]==stx[s]){
    43         scccnt++;
    44         while(1){
    45             int u=S.top();
    46             S.pop();
    47             scc[u]=scccnt;
    48             if(s==u)break;
    49         }
    50     }
    51 }
    52 
    53 void setscc(){
    54     memset(stx,0,sizeof(stx));
    55     memset(scc,0,sizeof(scc));
    56     memset(id,0,sizeof(id));
    57     memset(od,0,sizeof(od));
    58     numi=numo=t=scccnt=0;
    59     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
    60     if(scccnt!=1){
    61         for(int i=1;i<=n;++i){
    62             for(int j=head[i];~j;j=nxt[j]){
    63                 int k=point[j];
    64                 if(scc[i]!=scc[k]){
    65                     id[scc[i]]++;
    66                     od[scc[k]]++;
    67                     if(id[scc[i]]==1)numi++;
    68                     if(od[scc[k]]==1)numo++;
    69                 }
    70             }
    71         }
    72         numi=scccnt-numi;
    73         numo=scccnt-numo;
    74     }
    75 }
    76 
    77 int main(){
    78     int m;
    79     while(scanf("%d%d",&n,&m)!=EOF){
    80         init();
    81         while(m--){
    82             int a,b;
    83             scanf("%d%d",&a,&b);
    84             add(a,b);
    85         }
    86         setscc();
    87         printf("%d
    ",max(numi,numo));
    88     }
    89     return 0;
    90 }
    View Code
  • 相关阅读:
    校验身份证号、邮箱、手机号
    星级评分插件
    JS 实现轮播图
    js 禁止网页后退
    删除Redis缓存
    分析器错误,未能加载类型
    Vue 禁止按钮重复提交
    Vue 页面加载前显示{{代码}}的原因及解决办法 PC端
    设计模式之策略模式
    数据库索引知识到MySQL InnoDB
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4799152.html
Copyright © 2011-2022 走看看