zoukankan      html  css  js  c++  java
  • 受牛仰慕的牛

    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 3
    1 2
    2 1
    2 3

    Sample Output

    1【数据范围】
    10%的数据N<=20, M<=50
    30%的数据N<=1000,M<=20000
    70%的数据N<=5000,M<=50000
    100%的数据N<=10000,M<=50000
     
       1.找到所有强连通块
        2.计算所有联通块的出度
        3.如果有一个联通块出度为零,说明为最受欢迎的牛群
        4.如果存在两个联通块出度为零,说明不存在最受欢迎的牛
     
      1 #include <cstdlib>
      2 #include <iostream>
      3 #include <fstream>
      4 #include <cstring>
      5 /* run this program using the console pauser or add your own getch,  or input loop */
      6 
      7 using namespace std;
      8 
      9 ifstream fin("popular.in");
     10 ofstream fout("popular.out");
     11 
     12 int cows=0,roads=0;
     13 
     14 int head[10002]={0},cnt_lian=0;
     15 struct lian{
     16     int to;
     17     int next;
     18 };
     19 lian liansi[50002]={0};//链式前向星 
     20 
     21 int top=0;
     22 int stack[10002]={0};
     23 bool instack[10002]={0};//是否在栈里面 
     24 
     25 int cnt_dfn=0;//记录步数 
     26 int dfn[10002]={0};
     27 int low[10002]={0};
     28 
     29 
     30 
     31 int cnt_scc_node=0;//记录有几个联通块 
     32 int scc_node[10002]={0};//记录每个联通块里面有几个奶牛 
     33 int scc_belong[10002]={0};//记录每个奶牛属于几号联通块 
     34 
     35 bool cnt_chudu[10002]={0};//记录每个联通块是否有出度 
     36 
     37 void cun_lian(int a,int b);//存 链式前向星 
     38 void scc_meijv( );//枚举没有走到的点 
     39 void scc(int hao);//tarjan算法算联通块 
     40 
     41 void cun_lian(int a,int b){
     42      liansi[++cnt_lian].next=head[a];
     43      liansi[cnt_lian].to=b;
     44      head[a]=cnt_lian;
     45      return;
     46 }
     47 
     48 void scc_meijv(){
     49      for(int x=1;x<=cows;x++){
     50          if(dfn[x]==0)scc(x);//如果有一个点没走到,就去枚举 
     51      }
     52      return;
     53 }
     54 
     55 void scc(int hao){
     56      cnt_dfn++;
     57      dfn[hao]=cnt_dfn;
     58      low[hao]=cnt_dfn;//low默认为此时走到的步数 
     59      
     60      stack[++top]=hao;
     61      instack[hao]=true;//入栈 
     62     
     63      for(int x=head[hao];x!=-1;x=liansi[x].next){
     64          int dao=liansi[x].to;
     65          if(dfn[dao]==0){//如果没有算过 
     66                scc(dao);//就去计算 
     67               low[hao]=min(low[hao],low[dao]);
     68         }
     69         else if (instack[dao]){//如果在栈中 
     70            low[hao] = min(low[hao], dfn[dao]);           
     71         }
     72      }
     73     
     74      if(dfn[hao]==low[hao]){//表示出现了一个联通块 
     75         cnt_scc_node++;//联通块个数加一 
     76         int ding=0;
     77         do{
     78               ding=stack[top--];
     79               scc_belong[ding]=cnt_scc_node;
     80            scc_node[cnt_scc_node]++;     
     81               instack[ding]=false;//一个一个出栈,并作好记录 
     82            }while(ding!=hao);
     83     }
     84     
     85     return;
     86 }
     87 
     88 int main(int argc, char *argv[]) {
     89      fin>>cows>>roads;
     90     
     91      memset(head,-1,sizeof(head)); 
     92      for(int x=1;x<=roads;x++){
     93          int a,b;
     94          fin>>a>>b;    
     95          cun_lian(a,b);
     96     }
     97     
     98     
     99      scc_meijv();
    100     
    101      for(int x=1;x<=cows;x++){
    102          int size_x=scc_belong[x];
    103          for(int y=head[x];y!=-1;y=liansi[y].next){//搜索每一头奶牛的出度 
    104             if(cnt_chudu[size_x]==true)break;//如果这个奶牛所在的联通块已经有了出度,便可以不用计算.         
    105                int dao=liansi[y].to;
    106             int size_y=scc_belong[dao];
    107                if(size_x!=size_y){//如果枚举的奶牛的出度所连的不是同一个联通块 
    108                  cnt_chudu[size_x]=true; break;//表示这头奶油所在的联通块有了出度 
    109               }
    110          }    
    111      }
    112 
    113     int cnt_pop_scc=0;//记录出度为零的联通块 
    114     int cnt_pop_cow=0;//记录最受欢迎的牛的个数 
    115     for(int x=1;x<=cnt_scc_node;x++){//枚举每个联通块 
    116           if(cnt_chudu[x]==false){//如果有一个联通块出度为零    
    117              cnt_pop_scc++;//那么出度为零的联通块的个数加一 
    118              cnt_pop_cow+=scc_node[x];//加上里面所以奶牛 
    119            if(cnt_pop_scc>1){//当出度为零的联通块的个数大于一说明不存在最受欢迎的牛奶联通块 
    120                cnt_pop_cow=0; break;//最受欢迎的牛的个数为零 
    121              }    
    122          }    
    123     }
    124     
    125     
    126      cout<<cnt_pop_cow;
    127      fout<<cnt_pop_cow;
    128     
    129     return 0;
    130 }
    131 
    132 
  • 相关阅读:
    跳码与一机多终端
    SCRUM REPORT DIRECTORY
    ASE Backend Review
    ASE Beta Sprint
    ASE Beta Sprint
    ASE Backend Alpha Sprint Review
    ASE Alpha Sprint
    ASE Alpha Sprint
    ASE Alpha Sprint
    ASE Alpha Sprint
  • 原文地址:https://www.cnblogs.com/Ateisti/p/4869985.html
Copyright © 2011-2022 走看看