zoukankan      html  css  js  c++  java
  • 旅游电车

    【题目描述】

    首都有N个旅游景区,电车只沿道路规定的方向行驶,为了不使投入使用的电车有可能无法回到它的起始站,人们希望知道可以在哪些景区设置站点。

    一个景区可以被设置成车站,当且对于任意一个从该景区出发所能到达的景区,均至少有一条路可回到该景区。现已完成了一份景区之间的道路连通情况的报告,报告中将给出首都的景区数目N、道路总数M以及一些形如“景区A和景区B之间有一条从A到B的单向道路”的信息。根据报告中的信息,列出所有可以被设置成车站的景区。

    【输入描述】

    输入由多份报告组成(这些报告相互无任何联系),每份报告包括:

    第一行包含两个整数N、M;

    接下来M行,每行两个整数Ai、Bi表示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。

    源代码:
    
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<stack>
    using namespace std;
    stack <int> H;
    vector <int> S[5001];
    int n,m,Num,Ans,Head[5001],i[5001],j[5001];
    bool In[5001];
    void Tarjan(int t) //朴素Tarjan。
    {
        i[t]=j[t]=++Num;
        In[t]=true;
        H.push(t);
        for (int a=0;a<S[t].size();a++)
        {
            int T=S[t][a];
            if (!j[T])
            {
                Tarjan(T);
                i[t]=min(i[t],i[T]);
            }
            else
              if (In[T])
                i[t]=min(i[t],j[T]);
        }
        if (i[t]==j[t])
        {
            int k;
            Ans++;
            do
            {
                k=H.top();
                H.pop();
                Head[k]=Ans;
                In[k]=false;
            }
            while (k!=t);
        }
    }
    int main()
    {
        while (scanf("%d",&n)==1) //读入确实有点恶心。
        {
            if (!n)
              break;
            scanf("%d",&m);
            if (!m&&n==1)
            {
                printf("1
    ");
                continue;
            }
            Num=Ans=0;
            memset(j,0,sizeof(j)); //似乎只需要初始化j[]就好了。
            for (int a=0;a<m;a++)
            {
                int t1,t2;
                scanf("%d%d",&t1,&t2);
                S[t1].push_back(t2);
            }
            for (int a=1;a<=n;a++)
              if (!j[a])
                Tarjan(a);
            int Sum1[5001]={0},Sum2[5001]={0}; //Sum1[]表示入度,Sum2[]表示出度。
            for (int a=1;a<=n;a++) //缩点处理入度出度。
              for (int b=0;b<S[a].size();b++)
              {
                int k=S[a][b];
                if (Head[a]!=Head[k])
                {
                    Sum1[Head[k]]++;
                    Sum2[Head[a]]++;
                }
              }
            for (int a=1;a<=n;a++)
              if (!Sum2[Head[a]])
                printf("%d ",a);
            printf("
    ");
            for (int a=1;a<=n;a++) //初始化。
              S[a].clear();
        }
        return 0;
    }
    
    /*
        反思教训:
            没看到题目中“所能到达的节点必须能够返回”的条件,还得要认真细心。
    */
  • 相关阅读:
    centos7 安装kafka Manager
    MySql Table错误:is marked as crashed and last (automatic?) 和 Error: Table "mysql"."innodb_table_stats" not found
    安装prometheus+grafana监控mysql redis kubernetes等
    centos7 安装kubernetes1.4
    linux ip 转发设置 ip_forward
    开启Tomcat远程调试(转)
    SSH自动断开连接的原因、配置(转)
    解决mysql启动时报The server quit without updating PID file 的错误(转)
    supervisor的集中化管理搭建
    supervisor安装配置
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5838660.html
Copyright © 2011-2022 走看看