• 【强联通分量缩点】【Tarjan】bzoj1051 [HAOI2006]受欢迎的牛


    就是看是否有一些点,从其他任何点出发都可到达

    定理:有向无环图中唯一出度为0的点,一定可以由任何点出发均可达。

    所以缩点,若出度为零的点(强联通分量)唯一,则答案为该强联通分量中点的度数。

    若不唯一,答案为0,易证。

    Code(懒得Tarjan,用了两次DFS):

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 using namespace std;
     5 vector<int>order;
     6 int v[100001],first[100001],next[100001],en;
     7 int a[50001],b[50001],scc[10001],num[10001],sum,chu[10001];
     8 bool vis[10001];
     9 int n,m;
    10 inline void AddEdge(const int &U,const int &V){v[++en]=V;next[en]=first[U];first[U]=en;}
    11 void Clear()
    12 {
    13     memset(v,0,sizeof(v));
    14     memset(first,0,sizeof(first));
    15     memset(next,0,sizeof(next));
    16     en=0;
    17 }
    18 void dfs(int cur)
    19 {
    20     vis[cur]=true;
    21     for(int i=first[cur];i;i=next[i])
    22       if(!vis[v[i]])
    23         dfs(v[i]);
    24     order.push_back(cur);
    25 }
    26 void dfs2(int cur,int sum)
    27 {
    28     vis[cur]=true;
    29     scc[cur]=sum;
    30     num[sum]++;
    31     for(int i=first[cur];i;i=next[i])
    32       if(!vis[v[i]])
    33         dfs2(v[i],sum);
    34 }
    35 void Scc()
    36 {
    37     for(int i=1;i<=n;i++)
    38       if(!vis[i])
    39         dfs(i);
    40     memset(vis,false,sizeof(vis));Clear();
    41     for(int i=1;i<=m;i++)AddEdge(b[i],a[i]);
    42     int sz=order.size();
    43     for(int i=sz-1;i>=0;i--)
    44       if(!vis[order[i]])
    45         dfs2(order[i],++sum);
    46 }
    47 int Exam()
    48 {
    49     int cnt=0,Record;
    50     for(int i=1;i<=m;i++)
    51       if(scc[a[i]]!=scc[b[i]])
    52         chu[scc[a[i]]]++;
    53     for(int i=1;i<=sum;i++)
    54       if(!chu[i])
    55         {
    56           cnt++;
    57           Record=i;
    58           if(cnt==2)
    59             return 0;
    60         }
    61     return num[Record];
    62 }
    63 int res;char C;
    64 inline int Get()
    65 {
    66     res=0;C='*'; 
    67     while(C<'0'||C>'9')C=getchar();
    68     while(C>='0'&&C<='9'){res=res*10+(C-'0');C=getchar();}
    69     return res;
    70 }
    71 int main()
    72 {
    73     n=Get();m=Get();
    74     for(int i=1;i<=m;i++){a[i]=Get();b[i]=Get();AddEdge(a[i],b[i]);}
    75     Scc();printf("%d
    ",Exam());
    76     return 0;
    77 }
    ——The Solution By AutSky_JadeK From UESTC 转载请注明出处:http://www.cnblogs.com/autsky-jadek/
  • 相关阅读:
    深析Tomcat容器工作流程
    GC基础
    oracle sql总结
    mybatis返回值类型总结
    eclipse启动javaweb项目后,如何让局域网内的其他人访问
    oracle sql 逗号 分割 REGEXP_SUBSTR 函数
    Oracle12c安装时报"指定的oracle主目录用户已存在"错误
    spring
    Oracle sql where后面的多条件case when判断执行
    Oracle12c安装时报ins-30131
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/3963104.html
Copyright © 2020-2023  润新知