爱在心中(codevs 2822)

题目描述 Description

“每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动。爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home。”

在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况)。爱是具有传递性的,即如果A爱B,B爱C,则A也爱C。
如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使。
现在,我们想知道在这个爱的国度里会出现多少爱心天使。而且,如果某个爱心天使被其他所有人或爱心天使所爱则请输出这个爱心天使是由哪些人构成的,否则输出-1。

输入描述 Input Description

第1行,两个数N、M,代表爱的国度里有N个人,爱的关系有M条。
第2到第M+1行,每行两个数A、B,代表A爱B。

输出描述 Output Description

第1行,一个数,代表爱的国度里有多少爱心天使。
第2行,如果某个爱心天使被其他所有人和爱心天使所爱则请输出这个爱心天使是由哪些人构成的(从小到大排序),否则输出-1。

样例输入 Sample Input

样例输入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

样例输出 Sample Output

样例输出1:

2
2 3

样例输出2:

1
-1

/*
  tarjan求强连通分量,floyed进行关系更新 
*/
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
#define M 1010
using namespace std;
int num[M],low[M],vis[M],instack[M],belong[M],in[M],indexx,cnt,n,m;
int b[M],a[M][M];
vector<int> grap[M];
vector<int> tuan[M];
stack<int> s;
void tarjan(int v)
{
    num[v]=low[v]=++indexx;
    s.push(v);
    vis[v]=1;
    instack[v]=1;
    for(int i=0;i<grap[v].size();i++)
    {
        int w=grap[v][i];
        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(low[v]==num[v])
    {
        ++cnt;
        do
        {
            u=s.top();
            instack[u]=0;
            tuan[cnt].push_back(u);
            belong[u]=cnt;
            s.pop();
        }
        while(u!=v);
    }
}
void print(int x)
{
    for(int i=0;i<tuan[x].size();i++)
      b[i]=tuan[x][i];
    sort(b,b+tuan[x].size());
    for(int i=0;i<tuan[x].size();i++)
      printf("%d ",b[i]);
    printf("
");
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        grap[x].push_back(y);
    }
    for(int i=1;i<=n;i++)
      if(!vis[i])
        tarjan(i);
    int sum=0;
    for(int i=1;i<=cnt;i++)
      if(tuan[i].size()>1)
        sum++;
    printf("%d
",sum);
    for(int i=1;i<=n;i++)
      for(int j=0;j<grap[i].size();j++)
        if(belong[i]!=belong[grap[i][j]])
          a[belong[i]][belong[grap[i][j]]]=1;
    for(int k=1;k<=cnt;k++)
      for(int i=1;i<=cnt;i++)
        for(int j=1;j<=cnt;j++)
          if(a[i][k]&&a[k][j])
            a[i][j]=1;
    for(int i=1;i<=cnt;i++)
      for(int j=1;j<=cnt;j++)
        if(a[i][j])
          in[j]++;
    int flag=0;
    for(int i=1;i<=cnt;i++)
      if(in[i]==cnt-1&&tuan[i].size()>1)
      {
          flag=1;
          print(i);
      }
    if(!flag)printf("-1");
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/harden/p/5739804.html