zoukankan      html  css  js  c++  java
  • HAOI2006受欢迎的牛

    缩点裸题。

    题目链接:http://poj.org/problem?id=2186

    正确板子是 :1.缩点之后无需在意各连通块的大小,只需找出所有连通块都经过的那一个连通块;

           2.最后只需:有且仅有一个点(连通块)出度为0,则输出该点大小;其他情况一律输出0。

           (依据:①有向图缩点之后成为有向无环图;

               ②有向无环图中必有出度为0的点 + 若只有一个出度为0的点,则所有点都可到达该点;

               ③若有向无环图中有多个出度为0的点,则不存在 所有点都可到达的点。)

    自己用的深搜找那个所有点都可到达的点,但有谜:为何是>=n?何时重复了?

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m,x,y,xnt,nex[10005],rd[10005],cd[10005],dfn[10005],low[10005],sc[10005];
    int tim,s,in[10005],cnt,col[10005],siz,gs[10005];
    bool vis[10005],sid[10005][10005],flag[10005];
    struct Node{
        int next,to,from;
    }edge[50005];
    void add(int x,int y)
    {
        xnt++;
        edge[xnt].next=nex[x];
        edge[xnt].to=y;
        edge[xnt].from=x;
        nex[x]=xnt;
    }
    void tar(int a)
    {
        for(int i=nex[a];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(!dfn[v])
            {
                dfn[v]=++tim;
                low[v]=dfn[v];
                vis[v]=1;
                in[++cnt]=v;
                tar(v);
                if(low[v]<low[a])
                    low[a]=low[v];
            }
            else if(vis[v])
                      if(low[v]<low[a])low[a]=low[v];//找最早的 
        }
        if(dfn[a]==low[a])
        {
            siz++;
            int k=0;
            while(1)
            {
                k++;
                col[in[cnt]]=siz;
                vis[in[cnt]]=0;
                cnt--;
                if(in[cnt+1]==a)break;
            }
            sc[siz]=k;
            gs[siz]=k;
        }
    }
    void ser(int str,int zs)
    {
        int k=zs;
        if(!flag[str])
        {
            flag[str]=1;
            zs+=sc[str];
        }
        sc[str]+=k;
        if(!cd[str])return;
        for(int i=1;i<=siz;i++)
            if(sid[str][i])ser(i,zs);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i])
            {
                cnt=1;
                dfn[i]=++tim;
                low[i]=dfn[i];
                vis[i]=1;
                in[1]=i;
                tar(i);
            }
        for(int i=1;i<=m;i++)
        {
            int u=edge[i].from;
            int v=edge[i].to;
            if(col[u]!=col[v])
            {
                sid[col[u]][col[v]]=1;//col[u]
                rd[col[v]]++;
                cd[col[u]]++;
            }
        }
        
    //    for(int i=1;i<=siz;i++)//90  深搜
    //        if(!rd[i])
    //            ser(i,0);
    //    for(int i=1;i<=siz;i++)
    //        if(sc[i]>=n)    //由==改为>=则100 
    //            s+=gs[i];
                
    //    for(int i=1;i<=siz;i++)//85
    //        if(!cd[i])s+=gs[i];
    
        int uu=0;int kk=0;//100  结论
        for(int i=1;i<=siz;i++)
            if(!cd[i])uu++,kk=i;
        if(uu==1)printf("%d",gs[kk]);
        else printf("0");
    
    //    printf("%d",s);
        return 0;
    }
  • 相关阅读:
    一,初次接触html+css需要注意的小问题
    Pycharm如何在控制台输出窗口中使用Python解释器
    Silver Cow Party POJ
    Constructing Roads POJ
    小希的迷宫 HDU
    Wireless Network POJ
    Scanner读取记事本文件内容为空的解决办法
    mysql limit的使用方法
    Can you find it? HDU-2141 (二分查找模版题)
    【2028-07-18】精力是有限的,但智慧是无限的
  • 原文地址:https://www.cnblogs.com/Narh/p/8261689.html
Copyright © 2011-2022 走看看