zoukankan      html  css  js  c++  java
  • bzoj 1051: [HAOI2006]受欢迎的牛 tarjan缩点

    1051: [HAOI2006]受欢迎的牛

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2092  Solved: 1096
    [Submit][Status]

    Description

    每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。

    Input

    第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)

    Output

    一个数,即有多少头牛被所有的牛认为是受欢迎的。

    Sample Input

    3 3
    1 2
    2 1
    2 3

    Sample Output

    1

    【数据范围】
    10%的数据N<=20, M<=50
    30%的数据N<=1000,M<=20000
    70%的数据N<=5000,M<=50000
    100%的数据N<=10000,M<=50000
     
    突然发现以前的tarjan都时有问题的,vis标记应该出栈的时候打,而非退出是打。这道题缩点后判断“树根”本是非常简单的问题,然而由于思考不够深入,没有抓住"当且仅当DAG退化为“树”,才有解"的特性,所以编了半天还是错的。
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define MAXN 11000
    #define MAXV MAXN
    #define MAXE MAXN*20
    struct Edge
    {
            int np;
            Edge *next;
    }E[MAXE],*V[MAXV];
    int tope=-1;
    void addedge(int x,int y)
    {
            E[++tope].np=y;
            E[tope].next=V[x];
            V[x]=&E[tope];
    }
    int low[MAXN],dfn[MAXN];
    int dfstime=0;
    int stack[MAXN];
    int tops=-1;
    int color[MAXN],topc=0;
    int size_c[MAXN];
    int size_sub[MAXN];
    bool vis[MAXN];
    set<int> S[MAXN];
    void tarjan(int now)
    {
            low[now]=dfn[now]=++dfstime;
            Edge *ne;
            stack[++tops]=now;
            for (ne=V[now];ne;ne=ne->next)
            {
                    if (vis[ne->np])continue;
                    if (dfn[ne->np])
                    {
                            low[now]=min(low[now],dfn[ne->np]);
                    }else
                    {
                            tarjan(ne->np);
                            low[now]=min(low[now],low[ne->np]);
                    }
            }
            if (low[now]==dfn[now])
            {
                    ++topc;
                    while (stack[tops]!=now)
                    {
                            vis[stack[tops]]=true;
                            color[stack[tops--]]=topc;
                            size_c[topc]++;
                    }
                    vis[stack[tops]]=true;
                    color[stack[tops--]]=topc;
                    size_c[topc]++;
            }
    }
    pair<int,int> edge[MAXE];
    int topedge;
    int degree[MAXN];
    queue<int> Q;
    int main()
    {
            freopen("input.txt","r",stdin);
            int n,m;
            scanf("%d%d",&n,&m);
            int i,j,k,x,y,z;
            for (i=0;i<m;i++)
            {
                    scanf("%d%d",&x,&y);
                    addedge(x,y);
                    edge[i].first=x;
                    edge[i].second=y;
            }
            sort(edge,&edge[m]);
            topedge=0;
            for (i=1;i<m;i++)
            {
                    if (edge[i]!=edge[topedge])
                            edge[++topedge]=edge[i];
            }
            for (i=1;i<=n;i++)
            {
                    if (!dfn[i])tarjan(i);
            }
        //    memset(V,0,sizeof(V));
        //    tope=-1;
            for (i=0;i<m;i++)
            {
                    if (color[edge[i].first]==color[edge[i].second])continue;
            //        if (S[color[edge[i].first]].find(color[edge[i].second])!=S[color[edge[i].first]].end())continue;
        //            addedge(color[edge[i].first],color[edge[i].second]);
            //        S[color[edge[i].first]].insert(color[edge[i].second]);
                    degree[color[edge[i].first]]++;
            }
            int ans;
            ans=0;
            for (i=1;i<=topc;i++)
            {
                    if (degree[i]==0)ans++,x=i;
            }
            if (ans==1)
            {
                    printf("%d
    ",size_c[x]);
            }else
            {
                    printf("0
    ");
            }
            return 0;
    }
    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    5 Things Every Manager Should Know about Microsoft SharePoint 关于微软SharePoint每个经理应该知道的五件事
    Microsoft SharePoint 2010, is it a true Document Management System? 微软SharePoint 2010,它是真正的文档管理系统吗?
    You think you use SharePoint but you really don't 你认为你使用了SharePoint,但是实际上不是
    Introducing Document Management in SharePoint 2010 介绍SharePoint 2010中的文档管理
    Creating Your Own Document Management System With SharePoint 使用SharePoint创建你自己的文档管理系统
    MVP模式介绍
    权重初始化的选择
    机器学习中线性模型和非线性的区别
    神经网络激励函数的作用是什么
    深度学习中,交叉熵损失函数为什么优于均方差损失函数
  • 原文地址:https://www.cnblogs.com/mhy12345/p/3952110.html
Copyright © 2011-2022 走看看