zoukankan      html  css  js  c++  java
  • POJ 3275 Ranking the Cows (floyd传递闭包)

    Ranking the Cows
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 2248   Accepted: 1045

    Description

    Each of Farmer John's N cows (1 ≤ N ≤ 1,000) produces milk at a different positive rate, and FJ would like to order his cows according to these rates from the fastest milk producer to the slowest.

    FJ has already compared the milk output rate for M (1 ≤ M ≤ 10,000) pairs of cows. He wants to make a list of C additional pairs of cows such that, if he now compares those C pairs, he will definitely be able to deduce the correct ordering of all N cows. Please help him determine the minimum value of C for which such a list is possible.

    Input

    Line 1: Two space-separated integers: N and M 
    Lines 2..M+1: Two space-separated integers, respectively: X and Y. Both X and Y are in the range 1...N and describe a comparison where cow X was ranked higher than cow Y.

    Output

    Line 1: A single integer that is the minimum value of C.

    Sample Input

    5 5
    2 1
    1 5
    2 3
    1 4
    3 4

    Sample Output

    3

    Hint

    From the information in the 5 test results, Farmer John knows that since cow 2 > cow 1 > cow 5 and cow 2 > cow 3 > cow 4, cow 2 has the highest rank. However, he needs to know whether cow 1 > cow 3 to determine the cow with the second highest rank. Also, he will need one more question to determine the ordering between cow 4 and cow 5. After that, he will need to know if cow 5 > cow 3 if cow 1 has higher rank than cow 3. He will have to ask three questions in order to be sure he has the rankings: "Is cow 1 > cow 3? Is cow 4 > cow 5? Is cow 5 > cow 3?"

    Source

    题目:FJ想按照奶牛产奶的能力给她们排序。现在已知有N头奶牛(1 ≤ N ≤ 1,000)。FJ通过比较,已经知道了M(1 ≤ M ≤ 10,000)对相对关系。每一对关系表示为“X Y”,意指X的产奶能力强于Y。现在FJ想要知道,他至少还要调查多少对关系才能完成整个排序。

    思路:如果排序可以确定了,潜台词就是任意两头牛之间的关系都可以确定了。N头奶牛一共有C(N, 2) = N * (N - 1) / 2对关系。由现在已知的关系如能确认K对关系,则要调查的次数就是C(N, 2) - K。

    问题再思考一下就能发现,若u强于v,就连一条由u到v的有向路。两个节点之间有联系,就等价于这两个节点之间有一条有向路。这样就变成了任两点之间是否存在路径问题,用floyd传递闭包就可以了。

    但最多有1,000头奶牛,时间复杂度为O(N^3)。肯定会超,思考一下就会发现,枚举中间节点K之后就开始枚举起点u和终点v,若u与K,或者 v与K之间根本就不联通,那么绝对无法松弛。所以说更高效的方式就是起点只检查能通向K的节点,终点只检查K能通向的节点,这样就会把复杂度大大降低,因为边最多只有10000条。floyd 用边表实现,学习了。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 
     5 using namespace std;
     6 
     7 const int N=1010;
     8 
     9 int map[N][N],pre[N][N],suc[N][N];  //pre记录前驱,suc记录后继 pre[v][0]代表v的前驱的个数,suc[u][0]代表u的后继的个数
    10 
    11 int main(){
    12 
    13     //freopen("input.txt","r",stdin);
    14 
    15     int n,m;
    16     while(~scanf("%d%d",&n,&m)){
    17         memset(map,0,sizeof(map));
    18         memset(pre,0,sizeof(pre));
    19         memset(suc,0,sizeof(suc));
    20         int u,v;
    21         int cnt=m;
    22         while(m--){
    23             scanf("%d%d",&u,&v);
    24             map[u][v]=1;
    25             pre[v][++pre[v][0]]=u;  //v的前驱是u
    26             suc[u][++suc[u][0]]=v;  //u的后继是v
    27         }
    28         int i,j,k;
    29         for(k=1;k<=n;k++)
    30             for(i=1;i<=pre[k][0];i++){
    31                 u=pre[k][i];         //k的前驱是u
    32                 for(j=1;j<=suc[k][0];j++){
    33                     v=suc[k][j];        //k的后继是v
    34                     if(!map[u][v]){ //u是k的前驱,v是k的后继 所以u是v的前驱
    35                         pre[v][++pre[v][0]]=u;   //u 和 v 之间也建立关系
    36                         suc[u][++suc[u][0]]=v;
    37                         map[u][v]=1;
    38                         cnt++;
    39                     }
    40                 }
    41             }
    42         printf("%d\n",n*(n-1)/2-cnt);
    43     }
    44     return 0;
    45 }
  • 相关阅读:
    HTML-图片和多媒体
    HTML弹性布局
    HTML定位——绝对定位和相对定位、固定定位
    HTML定位和布局----float浮动
    CSS层叠
    HTML-css样式引用方式
    认识HTML和CSS
    原生js 进度条
    原生js文字滚动 滚动条
    时间轴
  • 原文地址:https://www.cnblogs.com/jackge/p/3025057.html
Copyright © 2011-2022 走看看