zoukankan      html  css  js  c++  java
  • 爱在心中

    【题目描述】

    在爱的国度里有N个人,他们都有所爱的人(不会出现自爱的情况),爱是具有传递性的,即如果A爱B,B爱C,则A也爱C。

    如果有这样一部分人,他们彼此都相爱,则他们就化身成为一个爱心天使。

    现在,我们想知道在这个爱的国度里会出现多少爱心天使,而且,如果某个爱心天使被其他所有人或爱心天使所爱,则请输出这个爱心天使是由哪些人构成的,否则输出-1。

    【输入描述】

    第一行输入两个数N、M,表示爱的国度里有N个人,爱的关系有M条;

    接下来M行,每行输入两个数A、B,表示A爱B。

    【输出描述】

    第一行输出一个数,表示爱的国度里有多少个爱心天使;

    第二行,如果某个爱心天使被其他所有人和爱心天使所爱,则输出这个爱心天使是由哪些人构成的(从小到大排序),否则输出-1。

    【样例输入】

    样例1:

    6 7

    1 2

    2 3

    3 2

    4 2

    4 5

    5 6

    6 4

    样例2:

    3 3

    1 2

    2 1

    2 3

    【样例输出】

    样例1:

    2

    2 3

    样例2:

    1

    -1

    源代码:
    
    #include<cstdio>
    #include<stack>
    #include<vector>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int m,n,Ans(0),Num(0),i[1001],j[1001]={0},Head[1001],Sum[1001]={0},Number[1001];
    bool Flag(0),In[1001]={0},f[1001][1001]={0};
    vector <int> S[1001];
    vector <int> F[1001];
    stack <int> H;
    void Tarjan(int t) //朴素Tarjan。
    {
        j[t]=i[t]=++Num;
        H.push(t);
        In[t]=true;
        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();
                In[k]=false;
                F[Ans].push_back(k);
                Head[k]=Ans;
            }
            while (k!=t);
        }
    }
    void Print(int t)
    {
        for (int a=0;a<F[t].size();a++)
          Number[a]=F[t][a];
        sort(Number,Number+F[t].size()); //设置新数组并从小到大输出。
        for (int a=0;a<F[t].size();a++)
          printf("%d ",Number[a]);
        printf("
    ");
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        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);
        Num=0;
        for (int a=1;a<=Ans;a++)
          if (F[a].size()>1)
            Num++;
        printf("%d
    ",Num); //爱心天使个数。
        for (int a=1;a<=n;a++)
          for (int b=0;b<S[a].size();b++)
            if (Head[a]!=Head[S[a][b]])
              f[Head[a]][Head[S[a][b]]]=true; //缩点并更新缩点的关系。
        for (int k=1;k<=Ans;k++)
          for (int a=1;a<=Ans;a++)
            for (int b=1;b<=Ans;b++)
              if (f[a][k]&&f[k][b])
                f[a][b]=true; //Floyd处理缩点关系。
        for (int a=1;a<=Ans;a++)
          for (int b=1;b<=Ans;b++)
            if (f[a][b])
              Sum[b]++; //统计入度。
        for (int a=1;a<=Ans;a++)
          if (Sum[a]==Ans-1&&F[a].size()>1) //判断是否符合输出条件。
          {
            Flag=true;
            Print(a);
          }
        if (!Flag)
          printf("-1");
        return 0;
    }
    
    /*
        一开始想到缩点这一块就想不动了,寻找合法的爱心天使我觉得是用DFS,嫌麻烦不想敲,而且细节也很多,后来看了题解发现Floyd就能处理节点之间的连通关系。
        还是要灵活地去想合适的算法,不要拘泥于想当然。
    */
  • 相关阅读:
    js调试工具
    学习之compare:c#和c++中各种compare方法
    individual program总结2.0
    individual program总结
    C语言编程—自动生成四则运算升级版
    jQuery Validate(一)
    Java_得到GET和POST请求URL和参数列表
    jQuery Validate(二)
    MySQL_使用时遇到的问题汇总
    jQuery Validate(三)
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5411131.html
Copyright © 2011-2022 走看看