POJ 2186(强连通分量 缩点)

来源:互联网 发布:淘宝漏洞q币充值系统 编辑:程序博客网 时间:2024/05/27 14:15

POJ 2186

题目大意

N头牛,现在给出M组关系(A,B)表示A喜欢B,喜欢具有传递性,问有多少头牛是被所有牛喜欢。

分析

对于每个强连通分量中,牛一定是互相喜欢的,所以我们可以先找出所有的强连通分量再缩点。

缩点后,如果一个节点能被所有节点走到,那么这个节点一定是叶子节点,出度为0(如果出度不为0必然为形成环),而且这样的节点只能有一个(因为这个节点不喜欢其他任何一个节点)

总结

几天没AC了,一直卡在POJ 2942使我不得开心颜,今天做道强连通分量水题20分钟写完一次AC平衡一下心态

代码

#include<cstdio>#include<iostream>#include<cmath>#include<cstring>#include<cstdlib>#include<queue>#include<map>#include<algorithm>#include<set>#include<stack>using namespace std;const int MAXN=100005;int n,m;int dfn[MAXN];int low[MAXN];int vis[MAXN];int belong[MAXN];int ti;int bcc_cnt;//缩点后的连通分量编号int in[MAXN];int out[MAXN];struct Edge{      int v;      int next;}edge[MAXN];int head[MAXN];int edgecount;void Init(){      memset(head,-1,sizeof(head));      memset(dfn,0,sizeof(vis));      memset(low,0,sizeof(low));      memset(vis,0,sizeof(vis));      memset(belong,0,sizeof(belong));      memset(in,0,sizeof(in));      memset(out,0,sizeof(out));      edgecount=0;      ti=0;      bcc_cnt=0;}void Add_edge(int u,int v){      edge[++edgecount].v=v;      edge[edgecount].next=head[u];      head[u]=edgecount;}stack<int> St;void Tarjan(int u){      dfn[u]=low[u]=++ti;      St.push(u);//入栈      vis[u]=1;      for(int k=head[u];k!=-1;k=edge[k].next)      {            int v=edge[k].v;            if(!dfn[v])//未被访问过            {                  Tarjan(v);                  low[u]=min(low[u],low[v]);            }            else if(vis[v]==1)//被访问过还在栈里里面            {                  low[u]=min(low[u],dfn[v]);            }      }      if(low[u]>=dfn[u])//      {            int x;            ++bcc_cnt;            while(1)            {                  x=St.top();                  St.pop();                  vis[x]=0;                  belong[x]=bcc_cnt;                  if(x==u)break;            }      }}void Solve(){      for(int i=1;i<=n;i++)            if(!dfn[i])Tarjan(i);     //统计缩点后每个点的入度和出度     for(int u=1;u<=n;u++)     {           for(int k=head[u];k!=-1;k=edge[k].next)           {                 int v=edge[k].v;                 if(belong[u]!=belong[v])                 {                       in[belong[v]]++;                       out[belong[u]]++;                 }           }     }     int node=0;     int sum=0;//统计出度为0的点的个数     for(int i=1;i<=bcc_cnt;i++)     {           if(out[i]==0){node=i;sum++;}     }     int ans=0;     for(int i=1;i<=n;i++)         if(belong[i]==node)ans++;     if(sum!=1) cout<<0<<endl;     else cout<<ans<<endl;}int main(){    int a,b;    while(scanf("%d%d",&n,&m)!=EOF)    {          Init();          for(int i=1;i<=m;i++)          {                scanf("%d%d",&a,&b);                Add_edge(a,b);          }          Solve();    }    return 0;}
0 0
原创粉丝点击