zoukankan      html  css  js  c++  java
  • POJ 1236(强连通分量)Tarjan+缩点

    以前写过这个题,因为还就不写tarjan了,用这道题熟悉一下。

    题目大意:
      给定一个n (n<=100)个点的有向图,问:
      Q1、最少需要选择多少个点,使得从这些点出发能遍历完整个图;
      Q2、最少需要添加多少条有向边,使得整个图成为连通图;
    分析:
            开始Q1我想复杂了,先说Q2吧,和hdu2767一样,当时我自己ac了hdu2767,可是做Q2的时候又一下没想到,便找出了原来的代码……
            先由Tarjan算法求出强连通分量后进行缩点,得到每个强连通分量的入度in[],出度out[];
      Q1: 入度为0的强连通分量个数; 
      Q2: max(  入度为0的强连通分量个数 ,  出度为0的强连通分量个数  );
    //题解 转自某神牛blog,忘了。。。代码自己的。
     
    View Code
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <iostream>
     5 #define M 100100
     6 #define N 5000
     7 using namespace std;
     8 int n,m,cnt,t,divg,belong[N],head[M],next[M],to[M],dfn[N],low[N],in[N],out[N],p,stack[N],innum,outnum;
     9 bool vis[N],fg[N];
    10 inline void add(int u,int v) 
    11 {
    12     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
    13 }
    14 void read()
    15 {
    16     memset(vis,0,sizeof vis);
    17     memset(dfn,0,sizeof dfn);
    18     memset(in,0,sizeof in);
    19     memset(out,0,sizeof out);
    20     memset(head,-1,sizeof head);cnt=0;
    21     divg=0; p=0; t=0;//时间标志 
    22     scanf("%d",&n);
    23     for(int i=1,a;i<=n;i++)
    24         while(scanf("%d",&a),a) add(i,a);
    25 }
    26 void dfs(int u)
    27 {
    28     t++;
    29     dfn[u]=low[u]=t;
    30     stack[++p]=u; fg[u]=true;
    31     for(int i=head[u];~i;i=next[i])
    32     {
    33         if(!dfn[to[i]])
    34         {
    35             dfs(to[i]);
    36             low[u]=min(low[u],low[to[i]]);
    37         }
    38         else if(fg[to[i]]) low[u]=min(low[u],dfn[to[i]]);
    39     }
    40     if(dfn[u]==low[u])
    41     {
    42         divg++;
    43         int tmp=-1;
    44         while(tmp!=u)
    45         {
    46             tmp=stack[p--];
    47             belong[tmp]=divg;
    48             fg[tmp]=false;
    49         }
    50     }
    51 }
    52 void go()
    53 {
    54     for(int i=1;i<=n;i++)
    55         if(!dfn[i]) dfs(i);
    56     for(int i=1;i<=n;i++)
    57         for(int j=head[i];~j;j=next[j])
    58             if(belong[i]!=belong[to[j]])
    59                 out[belong[i]]++,in[belong[to[j]]]++;
    60     innum=outnum=0;
    61     for(int i=1;i<=divg;i++)
    62     {
    63         if(!in[i]) innum++;
    64         if(!out[i]) outnum++;
    65     }
    66     printf("%d\n",innum);
    67     if(divg==1) printf("0\n");
    68     else printf("%d\n",max(innum,outnum));
    69 }
    70 int main()
    71 {
    72     read();
    73     go();
    74     system("pause");
    75     return 0;
    76 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    洛谷p1017 进制转换(2000noip提高组)
    Personal Training of RDC
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Eurasia
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Peterhof.
    Asia Hong Kong Regional Contest 2019
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Siberia
    XVIII Open Cup named after E.V. Pankratiev. Ukrainian Grand Prix.
    XVIII Open Cup named after E.V. Pankratiev. GP of SPb
    卜题仓库
    2014 ACM-ICPC Vietnam National First Round
  • 原文地址:https://www.cnblogs.com/proverbs/p/2662537.html
Copyright © 2011-2022 走看看