POJ-1236-Network of Schools

来源:互联网 发布:云计算定岗培训生骗局 编辑:程序博客网 时间:2024/05/24 01:46

这个题就是求强联通分量,然后缩点统计即可。

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<stack>using namespace std;const int maxn=110;const int maxm=maxn*maxn;int e,head[maxn],nxt[maxm],pnt[maxm],from[maxm],dfn[maxn],low[maxn],sccno[maxn],scc_no,dfs_clock;int n,cnt_in[maxn],cnt_out[maxn];stack<int> s;void AddEdge(int u,int v){    pnt[e]=v;from[e]=u;nxt[e]=head[u];head[u]=e++;}int Tarjan(int u){    dfn[u]=low[u]=++dfs_clock;    s.push(u);    for(int i=head[u];i!=-1;i=nxt[i])    {        if(!dfn[pnt[i]])            low[u]=min(low[u],Tarjan(pnt[i]));        else if(!sccno[pnt[i]])            low[u]=min(low[u],dfn[pnt[i]]);    }    if(low[u]==dfn[u])    {        scc_no++;        for(;;)        {            int x=s.top();s.pop();            sccno[x]=scc_no;            if(x==u)                break;        }    }    return low[u];}void solve(){    memset(cnt_in,0,sizeof(cnt_in));    memset(cnt_out,0,sizeof(cnt_out));    memset(dfn,0,sizeof(dfn));    memset(sccno,0,sizeof(sccno));    for(int i=1;i<=n;i++)        if(!dfn[i])            Tarjan(i);    if(scc_no==1)    {        printf("1\n0\n");        return;    }    for(int i=0;i<e;i++)        if(sccno[from[i]]!=sccno[pnt[i]])        {            cnt_out[sccno[from[i]]]++;            cnt_in[sccno[pnt[i]]]++;        }    int cntin=0,cntout=0;    for(int i=1;i<=scc_no;i++)    {        if(!cnt_in[i])            cntin++;        if(!cnt_out[i])            cntout++;    }    printf("%d\n%d\n",cntin,max(cntin,cntout));}int main(){    while(scanf("%d",&n)!=EOF)    {        e=scc_no=dfs_clock=0;        memset(head,-1,sizeof(head));        for(int i=1;i<=n;i++)        {            while(1)            {                int v;                scanf("%d",&v);                if(!v)                    break;                AddEdge(i,v);            }        }        solve();    }     return 0;}


0 0