poj 1236 强连通分量 缩点

来源:互联网 发布:诺基亚e5 00软件下载 编辑:程序博客网 时间:2024/05/18 00:39

有向无环图中所有入度不为0的点,一定 可以由某个入度为0的点出发可达。 

假定有 n 个入度为0的点,m个出度为0的点, max(m,n)就是第二个问题的解。

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <iostream>#include <algorithm>#include <queue>#include <stack>using namespace std;const int inf =0x3ffffff;const int maxn=10005;//点数struct edge{    int from,to,w,next;}e[50005];//边数stack<int>pq;int head[maxn];int instack[maxn];//是否在栈中int dfn[maxn];//同时可用于判断是否遍历过int low[maxn];int color[maxn],rdu[maxn],cdu[maxn];int n,m,t,index,se;//n个点,m条边,t用来生成边的标号,index用来生成点的标号void init()//建图前运行init{t=0;index=0;se=0;    memset(head,-1,sizeof(head));memset(instack,0,sizeof(instack));memset(dfn,-1,sizeof(dfn));memset(low,-1,sizeof(low));memset(color,-1,sizeof(color));memset(rdu,0,sizeof(rdu));memset(cdu,0,sizeof(cdu));while(!pq.empty())pq.pop();}void add(int i,int j,int w){    e[t].from=i;    e[t].to=j;    e[t].w=w;    e[t].next=head[i];    head[i]=t++;}void tarjan(int u){dfn[u]=low[u]=++index;pq.push(u);instack[u]=1;for(int i=head[u];i!=-1;i=e[i].next){if(dfn[e[i].to]==-1){tarjan(e[i].to);low[u]=min(low[u],low[e[i].to]);}else if(instack[e[i].to]==1){low[u]=min(low[u],dfn[e[i].to]);}}if(dfn[u]==low[u]){int v;v=pq.top();//从这个v开始为强连通分量的一个color[v]=se;pq.pop();instack[v]=0;while(v!=u){v=pq.top();color[v]=se;pq.pop();instack[v]=0;}se++;}}int main(){    int a,b,st;int i,j;    scanf("%d",&n);init();for(i=1;i<=n;i++){while(scanf("%d",&a)!=EOF && a!=0)add(i,a,0);}for(i=1;i<=n;i++){if(dfn[i]==-1)tarjan(i);}for(i=1;i<=n;i++)for(j=head[i];j!=-1;j=e[j].next){if(color[e[j].from]!=color[e[j].to]){cdu[color[e[j].from]]++;rdu[color[e[j].to]]++;}}int temp,cntr=0,cntc=0,ans=0;;for(i=0;i<se;i++){if(rdu[i]==0)cntr++;if(cdu[i]==0)cntc++;}if(se==1)printf("1\n0\n");elseprintf("%d\n%d\n",cntr,max(cntr,cntc));//system("pause");    return 0;}


0 0
原创粉丝点击