【POJ2186】受牛仰慕的牛

受牛仰慕的牛(popular cows)
  每头牛都有一个梦想:成为一个群体中最受欢迎的名牛!在一个有N(1<=N<=10,000)头牛的牛群中,给你M(1<=M<=50,000)个二元组(A,B),表示A认为B是受欢迎的。既然受欢迎是可传递的,那么如果A认为B受欢迎,B又认为C受欢迎,则A也会认为C是受欢迎的,哪怕这不是十分明确的规定。你的任务是计算被所有其它的牛都喜欢的牛的个数。

这道题直接考虑模拟是不行的,要考虑抽象模型。将仰慕关系建立成一个有向图,然后计算出强连通分量,缩点之后计算每个点的出度,如果有且只有一个点的出度为0,那么这头牛存在,否则不存在。
  要注意的是,缩点之后输出答案的时候,输出的是这个点(强连通分量)所包含的点数。

这道题是老师拿给我练习强连通的练手题。在强连通的算法上可以看出我对细节的把握还是不纯熟。比如忘记赋值DFN和LOW数组,还有就是对题目的抽象模型的能力分析不熟,如果不是老师告诉我这是强连通的话我估计是没有办法知道这道题的正确解法的。
  下附代码,同样不知道那时候的我在干什么。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <fstream>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <cmath>
  7 using namespace std;
  8 ifstream fin("popular.in");
  9 ofstream fout("popular.out");
 10 struct ls
 11 {
 12  int nw;
 13  int nxt;
 14 };
 15 ls qxx[50001];//链式前向星
 16 int cows=0,gx=0,bian=0,qlt=0,cs=0;
 17 int qlts[10001]={0};//每个强连通分量包含的点数
 18 int DFN[10001]={0},LOW[10001]={0},tou[10001]={0};
 19 int outs[10001]={0};//每个强连通分量的出度
 20 int from[10001]={0};//每个点所属的强连通分量
 21 bool rz[10001]={0};//每个点是否入栈
 22 bool pd[10001][10001]={0};//两个强连通分量之间是否相通
 23 int zhan[10001]={0},top=0;
 24 void add(int fr,int to);
 25 void add2(int fr,int to);
 26 void tarjan(int nw);
 27 int main(void)
 28 {
 29  fin>>cows>>gx;
 30  int a=0,b=0;
 31  memset(tou,-1,sizeof(tou));
 32  for(int i=1;i<=gx;i++)
 33     {
 34      fin>>a>>b;
 35      add(a,b);
 36     }
 37  for(int i=1;i<=cows;i++)
 38     {
 39      if(!DFN[i])tarjan(i);
 40     }
 41  int v=0;
 42  for(int i=1;i<=cows;i++)
 43     {
 44         for(int j=tou[i];j>0;j=qxx[j].nxt)
 45         {
 46          v=qxx[j].nw;
 47          if(from[i]!=from[v]&&!pd[from[i]][from[v]])add2(from[i],from[v]);
 48         }
 49     }
 50  int total=0,ans=0;
 51  for(int i=1;i<=qlt;i++)
 52     {
 53      if(outs[i]==0)
 54        {
 55         total++;
 56         ans+=qlts[i];
 57        }
 58     }
 59  if(total==1)fout<<ans;
 60  else fout<<"0";
 61  return 0;
 62 }
 63
 64 void add(int fr,int to)
 65 {
 66  bian++;
 67  qxx[bian].nw=to;
 68  qxx[bian].nxt=tou[fr];
 69  tou[fr]=bian;
 70 }
 71
 72 void tarjan(int nw)
 73 {
 74  top++;
 75  DFN[nw]=LOW[nw]=++cs;
 76  zhan[top]=nw;
 77  rz[nw]=true;
 78  int v=0;
 79  for(int i=tou[nw];i>0;i=qxx[i].nxt)
 80     {
 81      v=qxx[i].nw;
 82      if(!DFN[v])
 83        {
 84         tarjan(v);
 85         LOW[nw]=min(LOW[v],LOW[nw]);
 86        }
 87      else
 88        {
 89         if(rz[v]==true)
 90           {
 91            LOW[nw]=min(LOW[nw],DFN[v]);
 92           }
 93        }
 94     }
 95  if(DFN[nw]==LOW[nw])
 96    {
 97     qlt++;
 98     do
 99     {
100      v=zhan[top];
101      from[v]=qlt;
102      qlts[qlt]++;
103      rz[v]=false;
104      top--;
105     }while(nw!=v);
106    }
107  return;
108 }
109
110 void add2(int fr,int to)
111 {
112  pd[fr][to]=true;
113  outs[fr]++;
114  return;
115 }
时间: 2024-10-11 07:14:34

【POJ2186】受牛仰慕的牛的相关文章

受牛仰慕的牛

Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎.你的任务是求出有多少头牛被所有的牛认为是受欢迎的. Input 第一行两个数N,M. 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B) Output 一个数,即有多少头牛被所有的牛认为是受欢迎的. Sample Input 3 31

不裸缩点》。。。POJ2186受欢迎的牛

html,body { font-size: 15px } body { font-family: Helvetica, "Hiragino Sans GB", "微软雅黑", "Microsoft YaHei UI", SimSun, SimHei, arial, sans-serif; line-height: 1.6; margin: 0; padding: 1.33rem 1rem } h1,h2,h3,h4,h5,h6 { margin

poj 2481 Cows(输出每头牛有几头牛比其强壮,明牛i比牛j强壮:Si &lt;=Sjand Ej &lt;= Ei and Ei - Si &gt; Ej - Sj)

Cows Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 15834 Accepted: 5271 Description Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in his fi

【牛客】牛客练习赛16(未完)

A  字典序最大的子序列 题意:给定字符串s,s只包含小写字母,请求出字典序最大的子序列.(看例子就能看明白) 思路:从这个字符串a后面开始比较,先把最后一个字母存进s,然后那那s中最新的一个元素跟a中上一个进行比较,如果a不比s小,则存入s,并把这个看做新哒~ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; char s[100007]; int ma

POJ 2186 Popular Cows(Targin缩点)

传送门 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31808   Accepted: 12921 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <=

连通图练习总结

连通图是图论基于联通的一个概念,在ACM中针对图论的考察一部分是也是基于连通图.针对这类问题的解题基本思路就是先求出对应的连通分量(有向图的强连通,无向图的双连通)对图进行简化,然后再结合其他算法计算. 1. POJ 3180 The Cow Prom 这个题如果能理解题目的话,怎么做就很明显了,能形成一个可以转圈的小群,就相当于一个强连通分量,需要注意的就是这个小群不可以只有一头牛. #include <set> #include <map> #include <list&

bzoj1051【HAOI2006】受欢迎的牛

1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3491  Solved: 1837 [Submit][Status][Discuss] Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎.你的任务是求出有多少头牛被所有的牛认为是受欢迎的. I

HAOI2006 受欢迎的牛

HAOI2006 ]受欢迎的牛 Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛 A 认为牛 B受欢迎.这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎.你的任务是求出有多少头牛被所有的牛认为是受欢迎的. Input 第1行两个整数N,M: 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B) Output 一个数,即有多少头牛被所有的牛认为是受欢迎的

[BZOJ1051] [HAOI2006] 受欢迎的牛 (强联通分量)

Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这 种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎.你的任务是求出有多少头 牛被所有的牛认为是受欢迎的. Input 第一行两个数N,M. 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可 能出现多个A,B) Output 一个数,即有多少头牛被所有的牛认为是受欢迎的. Sample Input 3