• poj 1236(强连通分量)


    题目大意:   给定一个n (n<=100)个点的有向图,

    问:Q1、最少需要选择多少个点,使得从这些点出发能遍历完整个图; 

      Q2、最少需要添加多少条有向边,使得整个图成为强连通图; 

      分析: 

        求出强连通分量后进行缩点,得到每个强连通分量的入度in[],出度out[]; 

      Q1: 入度为0的强连通分量个数;   Q2: max( 入度为0的强连通分量个数 , 出度为0的强连通分量个数  );

      注意的地方:假如原图就是一个强连通图。则显然Q2是0.

    kosaraju:

    View Code
      1 // File Name: 1236.cpp
      2 // Author: Missa
      3 // Created Time: 2013/2/6 星期三 19:44:12
      4 
      5 #include<iostream>
      6 #include<cstdio>
      7 #include<cstring>
      8 #include<algorithm>
      9 #include<cmath>
     10 #include<queue>
     11 #include<stack>
     12 #include<string>
     13 #include<vector>
     14 #include<cstdlib>
     15 #include<map>
     16 using namespace std;
     17 
     18 const int maxn = 1e2+5;
     19 int n;
     20 vector<int>adj[maxn];
     21 vector<int>radj[maxn];
     22 vector<int>ord;
     23 bool vis[maxn];
     24 int ma[maxn];
     25 int cnt;
     26 void init()
     27 {
     28     for(int i=0;i<maxn;i++)
     29     {
     30         adj[i].clear();
     31         radj[i].clear();
     32     }
     33     ord.clear();
     34     cnt=0;
     35 }
     36 void dfs1(int v)
     37 {
     38     vis[v]=1;
     39     for(int i=0;i<adj[v].size();i++)
     40         if(!vis[adj[v][i]])
     41             dfs1(adj[v][i]);
     42     ord.push_back(v);
     43 }
     44 void dfs2(int v)
     45 {
     46     vis[v]=1;
     47     ma[v]=cnt;
     48     for(int i=0;i<radj[v].size();i++)
     49         if(!vis[radj[v][i]])
     50             dfs2(radj[v][i]);
     51 }
     52 void kosaraju()
     53 {
     54     memset(vis,0,sizeof(vis));
     55     ord.clear();
     56     for(int i=1;i<=n;i++)
     57         if(!vis[i])
     58             dfs1(i);
     59     memset(vis,0,sizeof(vis));
     60     cnt=0;
     61     for(int i=ord.size()-1;i>=0;i--)
     62     {
     63         if(!vis[ord[i]])
     64         {
     65             cnt++;
     66             dfs2(ord[i]);
     67         }
     68     }
     69 }
     70 void read()
     71 {
     72     for(int i=1;i<=n;i++)
     73     {
     74         int x;
     75         while(scanf("%d",&x))
     76         {
     77             if(x==0) break;
     78             adj[i].push_back(x);
     79             radj[x].push_back(i);
     80         }
     81     }
     82 }
     83 void solve()
     84 {
     85     int ans1=0,ans2=0;
     86     int in[maxn],out[maxn];//入度,出度
     87     memset(in,0,sizeof(in));
     88     memset(out,0,sizeof(out));
     89     for(int i=1;i<=n;i++)
     90     {
     91         for(int j=0;j<adj[i].size();j++)
     92         {
     93             int tt=adj[i][j];
     94             if(ma[i]==ma[tt]) continue;
     95             out[ma[i]]++;
     96             in[ma[tt]]++;
     97         }
     98     }
     99     for(int i=1;i<=cnt;i++)
    100     {
    101         if(in[i]==0) ans1++;
    102         if(out[i]==0) ans2++;
    103     }
    104     printf("%d\n",ans1);
    105     if(cnt==1)//原图是一个强连通分量
    106         printf("0\n");
    107     else
    108         printf("%d\n",max(ans1,ans2));
    109 }
    110 int main()
    111 {
    112     while(~scanf("%d",&n))
    113     {
    114         init();
    115         read();
    116         kosaraju();
    117         solve();
    118     }
    119     return 0;
    120 }
  • 相关阅读:
    代码重构~方法归子
    代码重构~代码注释
    VS2010安装帮助文档
    imagecreate()与imagecreatetruecolor()区别
    php cookie 和session详解
    horner's rule霍纳法则及综合除法
    php单引号和双引号的区别与用法
    php通过session判断用户是否登录
    php 产生验证码
    基于递归的整数幂的计算
  • 原文地址:https://www.cnblogs.com/Missa/p/2908139.html
Copyright © 2020-2023  润新知