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就能处理节点之间的连通关系。
        还是要灵活地去想合适的算法,不要拘泥于想当然。
    */
  • 相关阅读:
    winform+c#之窗体之间的传值 Virus
    ASP.NET 2.0 利用 checkbox获得选中行的行号, 在footer中显示 Virus
    .NET中的winform的listview控件 Virus
    我的书橱
    Expert .NET 2.0 IL Assembler·译者序一 写在一稿完成之即
    Verbal Description of Custom Attribute Value
    AddressOfCallBacks in TLS
    下一阶段Schedule
    2008 Oct MVP OpenDay 第二天 博客园聚会
    2008 Oct MVP OpenDay 第二天 颁奖·讲座·晚会
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5411131.html
Copyright © 2011-2022 走看看