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

     

    2822 爱在心中
    时间限制: 1 s
    空间限制: 128000 KB
    题目等级 : 钻石 Diamond

    题目描述 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缩点

    缩完的点是连通分量,当且仅当缩完的点中包含至少两个原来的点

    统计含有至少两个点的联通块的个数,下边的询问同bzoj1051受欢迎的牛,输出出度为0且点权>=2的点中的原来的点 

    #include<cstdio>
    #define N 10010
    #define M 50010
    struct edge{
    	int to,next;
    }e[M];
    int n,m;
    int head[N];
    int pre[N],low[N];
    int sccnum[N],have[N];
    int cnt,cnt2,cnt3,top;
    int zhan[3*N];
    int p[N];
    inline int min(int a,int b)
    {return a<b?a:b;}
    inline void ins(int u,int v)
    {
    	e[++cnt].to=v;
    	e[cnt].next=head[u];
    	head[u]=cnt;
    }
    inline void rebuild()
    {
    	for (int i=1;i<=n;i++)
    	  for (int j=head[i];j;j=e[j].next)
    	    if (sccnum[i]!=sccnum[e[j].to])
    	      p[sccnum[i]]++;
    }
    inline void dfs(int x)
    {
    	zhan[++top]=x;
    	low[x]=pre[x]=++cnt2;
    	for (int i=head[x];i;i=e[i].next)
    	{
    	  if(!pre[e[i].to])
    	  {
    	  	dfs(e[i].to);
    	  	low[x]=min(low[x],low[e[i].to]);
    	  }else if(!sccnum[e[i].to])
    	     low[x]=min(low[x],pre[e[i].to]);
    	}
    	if (pre[x]==low[x])
    	{
    		cnt3++;
    		int p=-1;
    		while (p!=x)
    		{
    			p=zhan[top];
    			top--;
    			sccnum[p]=cnt3;
    			have[cnt3]++;
    		}
    	}
    }
    inline void tarjan()
    {
    	for (int i=1;i<=n;i++)
    	  if (!pre[i]) dfs(i);
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	  {
    	  	int x,y;
    	  	scanf("%d%d",&x,&y);
    	  	ins(x,y);
    	  }
    	tarjan();
    	int tot=0;
    	for (int i=1;i<=n;i++)
    	  if (have[i]>1)tot++;
    	printf("%d
    ",tot);
    	rebuild();
    	tot=0;
    	int sav;
    	for (int i=1;i<=cnt3;i++)
    	  if (!p[i]&&have[i]>1)tot++,sav=i;
    	if (tot>1||!tot)
    	{
    		printf("-1
    ");
    		return 0;
    	}
    	for (int i=1;i<=n;i++)
    	  if (sccnum[i]==sav)printf("%d ",i);
    }
    

      

    ——by zhber,转载请注明来源
  • 相关阅读:
    DLL注入之Appinit_Dlls
    VC下遍历文件夹中的所有文件的几种方法
    Windows下C语言的Socket编程例子(TCP和UDP)
    Windows进程间共享内存通信实例
    window下线程同步之(Mutex(互斥器) )
    如何安装win10和linux [ubuntu14]双系统
    Windows虚拟地址转物理地址(原理+源码实现,附简单小工具)
    Windows驱动中通过MDL实现用户态与核心态共享内存
    C# Label显示多行文本及换行(WinForm/WebForm)
    使用delegate实现简单的查询功能
  • 原文地址:https://www.cnblogs.com/zhber/p/4035912.html
Copyright © 2011-2022 走看看