zoukankan      html  css  js  c++  java
  • 旅游电车(cogs 1175)

    【问题描述】

    Henryy国正致力于首都的一个旅游电车建设工程。首都有N个旅游景区。Henryy国的电车永远只沿道路规定的方向行驶,为了不使投入使用的电车有可能无法回到它的起始站,Henryy希望知道他的首都的可以在哪些景区设置站点。一个景区可以被设置成车站,当且仅当对于任意一个从该景区出发所能到达的景区,均至少有一条路可回到该景区。你的同事已完成了一份景区之间的道路连通情况的报告。报告中将给出首都的景区数目N、道路总数M以及一些形如“景区A和景区B之间有一条从A到B的单向道路”的信息。现在明确你的任务:根据报告中的信息,列出所有可以被设置成车站的景区。

    【输入文件】

    输入文件由多份报告组成(这些报告相互无任何联系),每份报告包括:N,M,接下来M对整数Ai、Bi (1<=I<=M)表示Ai和Bi之间有一条单向道路Ai->Bi。仅一个包含整数N=0的报告表示你的工作结束,你的程序不应该对此有任何反应。各整数间用空格或空行分隔。对于任意景区,分别以该景区为起点或终点的道路总数均不超过50。

    【输出文件】

    对于每份报告,输出一行列表包括:所有能被设置成电车站点的景区编号,各编号之间用一个空格隔开。

    【样例输入】

    5 6
    1 2
    2 3
    3 4
    4 1
    2 5
    5 2
    1 0
    0

    【样例输出】

    1 2 3 4 5
    1

    【数据约定】

    对于40%的数据,有N<=200。
    对于100%的数据,有N<=5000,M<=50000。

    /*
      tarjan算法
      题目要求求出的点满足它能连到的点也能连回来,那么就一定要与它在同一缩点中,如果一个缩点出度大于1,那么这个缩点中的所有点都不满足要求。
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #define M 5010
    using namespace std;
    int num[M],low[M],instack[M],vis[M],belong[M],out[M],a[M][M],s
    
    [M*2],cnt,indexx,top;
    int head[M],n,m,ans[M];
    struct node
    {
        int v,pre;
    };node e[M*10];
    int read()
    {
        char c=getchar();int num=0,flag=1;
        while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
        while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
        return num*flag;
    }
    void add(int i,int x,int y)
    {
        e[i].v=y;
        e[i].pre=head[x];
        head[x]=i;
    }
    void tarjan(int v)
    {
        num[v]=low[v]=++indexx;
        vis[v]=instack[v]=1;
        s[++top]=v;
        for(int i=head[v];i;i=e[i].pre)
        {
            int w=e[i].v;
            if(!vis[w])
            {
                tarjan(w);
                low[v]=min(low[v],low[w]);
            }
            else if(instack[w])
              low[v]=min(low[v],num[w]);
        }
        int u;
        if(num[v]==low[v])
        {
            ++cnt;
            do
            {
                u=s[top--];
                instack[u]=0;
                belong[u]=cnt;
                a[cnt][++a[cnt][0]]=u;
            }while(u!=v);
        }
    }
    void work()
    {
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read();
            add(i,x,y);
        }
        for(int i=1;i<=n;i++)
          if(!vis[i])tarjan(i);
        for(int i=1;i<=n;i++)
          for(int j=head[i];j;j=e[j].pre)
            if(belong[i]!=belong[e[j].v])
              out[belong[i]]++;
        int k=0;
        for(int i=1;i<=cnt;i++)if(!out[i])
          for(int j=1;j<=a[i][0];j++)
            ans[++k]=a[i][j];
        sort(ans+1,ans+k+1);
        for(int i=1;i<=k;i++)
          printf("%d ",ans[i]);
        printf("
    ");
    }
    int main()
    {
        freopen("buss.in","r",stdin);
        freopen("buss.out","w",stdout);
        while(1)
        {
            n=read();if(!n)break;
            m=read();
            memset(head,0,sizeof(head));
            memset(num,0,sizeof(num));
            memset(low,0,sizeof(low));
            memset(vis,0,sizeof(vis));
            memset(instack,0,sizeof(instack));
            memset(s,0,sizeof(s));
            memset(e,0,sizeof(e));
            memset(belong,0,sizeof(belong));
            memset(out,0,sizeof(out));
            memset(a,0,sizeof(a));
            indexx=cnt=top=0;
            work();
        }
        return 0;
    }
    View Code

     

  • 相关阅读:
    Java学习-IO流-read()和write()详解
    JAVA中String类常用构造方法
    java的System.exit(0)和System.exit(1)区别。
    Eclipse快捷键大全
    Java Arraylist的遍历
    Java Map的遍历
    C++求最大公约数,最小公倍数
    C++sort使用实例
    [Project Euler] 题目汇总
    [leetcode]做过的题的目录
  • 原文地址:https://www.cnblogs.com/harden/p/5840204.html
Copyright © 2011-2022 走看看