动态规划(6)Popular Cows poj2186

来源:互联网 发布:java rar压缩与解压 编辑:程序博客网 时间:2024/06/06 00:24
Popular Cows
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 18989 Accepted: 7623

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 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive, if A thinks B is popular and B thinks C is popular, then A will also think that C is
popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow.

Input

* Line 1: Two space-separated integers, N and M

* Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.

Output

* Line 1: A single integer that is the number of cows who are considered popular by every other cow.

Sample Input

3 31 22 12 3

Sample Output

1

Hint

Cow 3 is the only cow of high popularity.

Source

USACO 2003 Fall
 
 
题意是求出受全部牛崇拜的的牛的个数,而不是最受欢迎的牛的个数(WA了好多次。。)
这一题用的是深搜+强连通分量,用Tarjan算法只用一次DFS,也可以用korasaju算法求。
Tarjan:
#include<stdio.h>#include<string.h>#include<algorithm>#include<stdlib.h>using namespace std;#define N 10005#define M 50005struct node{int u,v,next;//u:边的起始点;v:边的终点。next:以u为起点的下一条边的编号}edge[M];int outd[N];int low[N],dfn[N],scc,belong[N];bool ins[N];//dfn[i]表示编号为i的节点在DFS过程中的访问时间(开始时间);//low[i]表示从i节点出发DFS过程中i的下方节点(开始时间大于dfn[i],且由i可达的节点)所能到达的最早的节点的开始时间。//初始时low[i] = dfn[i];//ins[i]表示i是否在栈中,1表示在,0表示不在。//belong染色,分强连通分量。scc,表示第几个强连通分量。int stack[N],top,index,n,m,e,head[N];//head[x]是指以x为起点的最后一条边的编号,初始化为-1.bool vis[N];//是否被访问。void init(){top = index = e = scc = 0;     memset(dfn, 0, sizeof(dfn));  //memset(low, 0, sizeof(low)); memset(vis, false, sizeof(vis));      memset(ins, false, sizeof(ins));      memset(outd, 0, sizeof(outd));  memset(head, -1, sizeof(head));  }void addedge(int u,int v)//加边,邻接表{edge[e].u = u;edge[e].v = v;edge[e].next = head[u];head[u] = e++;}void dfs(int u){int v;dfn[u] = low[u] = ++index; stack[top++] = u;//入栈vis[u] = true;ins[u] = 1;for(int i=head[u];i!=-1;i = edge[i].next)//遍历边{  v = edge[i].v;if(!dfn[v] && !vis[v]){     dfs(v);     low[u] = min(low[u],low[v]);//如果u 的子节点能够到达更早的时间,那么u一定也能。}else if(ins[v]){     low[u] = min(low[u],dfn[v]);//如果已经在栈里,就取子节点的发现时间和u的low值较小值。}}if(dfn[u] == low[u])//找到了一个强连通分量。{++scc;do{v = stack[--top];stack[top] = 0;//退栈。ins[v] = 0;belong[v] = scc;}while(u!=v);}}void Tarjan(){for(int i=0;i<m;i++){if(!dfn[edge[i].u])dfs(edge[i].u);}}void countoutdeg()//求强连通分量缩点后的出度{for (int u=1; u<=n; ++u)         for (int i=head[u]; i!=-1; i=edge[i].next)        {            int v = edge[i].v;            if (belong[u] != belong[v])            {                              outd[belong[u]]++;            }        }}int main(){int i,u,v,x;while(~scanf("%d %d",&n,&m)){init();for(i = 1;i<=m;i++){scanf("%d %d",&u,&v);addedge(u,v);}Tarjan();countoutdeg();int count=0;for(i=1;i<=scc;i++)if(outd[i]==0) {++count;        x=i;}for(i=1;i<=n;i++)if(!vis[i]) count++;//确保求的是被所有的牛所欢迎的if(count > 1)  printf("0\n");else{count = 0;for(i=1;i<=n;i++)if(belong[i] == x)//出度为0的强连通分量只能有一个,否则就输出0了,所以x是唯一的。++count;printf("%d\n",count); }}//system("pause");return 0;}

 
 
 
原创粉丝点击