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 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    广度优先搜索
    洛谷 P1126 机器人搬重物
    codevs 1058 合唱队形
    洛谷P1216 [USACO1.5]数字三角形 Number Triangles
    Codevs 1576 最长严格上升子序列
    跳马(Knight Moves), ZOJ1091, POJ2243
    洛谷 P1644 跳马问题
    NOI 2971 抓住那头牛
    NOI 2727 仙岛求药
    搜索与回溯算法
  • 原文地址:https://www.cnblogs.com/proverbs/p/2662537.html
Copyright © 2011-2022 走看看