zoukankan      html  css  js  c++  java
  • POJ 1236 Network of Schools

    POJ_1236

        这个题目的TaskA实际上就是在求入度为0的强连通分量的个数,而TaskB实际上就是在求各个强连通分量中入度为0的个数与出度为0的个数的较大值。

        同时这个题目与之前做的点双连通的分量有所不同,其中有一点便是在求强连通分量时对于low[u]>dfn[v]时更新low[u]的值,有一个前提条件就是v在栈内,因而要单独用一个数组标记v是否在栈内,而求点双连通分量时则不需要这个数组,因为只要G[u][v]为1,且dfn[v]不为0,那么v一定在栈中。

        对于双连通分量为什么不需要标记v是否在栈内,可以先假设v不在栈中但dfn[v]不为0,而如果G[u][v]为1,那么在dfs的过程中,要么v应该在u的后面被搜到,那么dfn[v]显然应该为0,这样与假设矛盾,或者v应该在u的前面被搜到,那么由于u在v后面,v出栈之前必定u已经出栈了,而现在u又确实在栈里,这也是矛盾的(因为出栈后的元素不会再进栈),所以对于求点双连通分量的过程,如果在dfs过程中出现了G[u][v]为1且dfn[v]不等于0的情况,那么v一定在栈中。

    #include<stdio.h>
    #include
    <string.h>
    int ans[110][110],indgr[110],outdgr[110],G[110][110];
    int ins[110],s[110],top,num,N,dfn[110],low[110],time;
    void tarjan(int u)
    {
    int i,v;
    dfn[u]
    =low[u]=++time;
    s[top
    ++]=u;
    ins[u]
    =1;
    for(v=0;v<N;v++)
    if(G[u][v])
    {
    if(!dfn[v])
    {
    tarjan(v);
    if(low[v]<low[u])
    low[u]
    =low[v];
    }
    elseif(ins[v]&&dfn[v]<low[u])
    low[u]
    =dfn[v];
    }
    if(dfn[u]==low[u])
    {
    s[top]
    =-1;
    for(i=0;s[top]!=u;i++)
    {
    ans[num][i]
    =s[--top];
    ins[ans[num][i]]
    =0;
    }
    num
    ++;
    }
    }
    int main()
    {
    int i,j,k,taskB,p,q,taskA,ok,u;
    while(scanf("%d",&N)==1)
    {
    for(i=0;i<N;i++)
    while(1)
    {
    scanf(
    "%d",&j);
    if(j==0)
    break;
    j
    --;
    G[i][j]
    =1;
    }
    memset(ans,
    -1,sizeof(ans));
    memset(ins,
    0,sizeof(ins));
    memset(dfn,
    0,sizeof(dfn));
    time
    =num=top=0;
    for(u=0;u<N;u++)
    if(!dfn[u])
    tarjan(u);
    if(num==1)
    {
    printf(
    "1\n0\n");
    continue;
    }
    memset(indgr,
    0,sizeof(indgr));
    memset(outdgr,
    0,sizeof(outdgr));
    for(i=0;i<num;i++)
    for(j=0;j<num;j++)
    {
    if(i==j)
    continue;
    ok
    =0;
    for(p=0;ans[i][p]!=-1;p++)
    {
    for(q=0;ans[j][q]!=-1;q++)
    if(G[ans[i][p]][ans[j][q]])
    {
    indgr[j]
    ++;
    outdgr[i]
    ++;
    ok
    =1;
    break;
    }
    if(ok)
    break;
    }
    }
    taskB
    =taskA=0;
    for(i=0;i<num;i++)
    {
    if(indgr[i]==0)
    taskA
    ++;
    if(outdgr[i]==0)
    taskB
    ++;
    }
    taskB
    =taskB>taskA?taskB:taskA;
    printf(
    "%d\n%d\n",taskA,taskB);
    }
    return0;
    }
  • 相关阅读:
    Linux——k8s命令别名修改
    k8s—centos7安装部署NFS服务器和客户端及基于nfs的动态存储storageclass使用总结
    MySQL—用户和权限管控
    MySQL—常用SQL语句整理总结
    Zookeeper——入门介绍(相关原理、安装启动及使用操作)
    SpringBoot——Quartz定时框架的使用详解和总结
    SpringBoot——@Scheduled的自定义周期性线程池解决任务延时执行问题
    Linux—用户新建目录和文件的默认权限设置:umask详解
    设计模式——单例模式详解
    Linux—CPU核数、上下文切换介绍及pidstat等命令详解
  • 原文地址:https://www.cnblogs.com/staginner/p/2135342.html
Copyright © 2011-2022 走看看