奶牛排序问题

x33g5p2x  于2022-06-27 转载在 其他  
字(1.5k)|赞(0)|评价(0)|浏览(290)

一 原问题描述

3275 -- Ranking the Cows

http://poj.org/problem?id=3275

二 输入与输出

1 输入

第1行包含两个整数 N 和 M。第 2 到 M+1 行,每行都包含两个整数 X 和 Y。X 和 Y 都是在 1 到 N 范围内,表示奶牛 X 的排名高于奶牛 Y。

2 输出

单行输出至少要调查多少种关系才能完成整个排序。

3 输入样例

5 5

2 1

1 5

2 3

1 4

3 4

4 输出样例

3

三 算法分析与设计

1 根据输入样例,创建一个有向图

2 根据传递性,得到的7种关系,分别是

1>4

1>5

2>1

2>3

2>4

2>5

3>4

3 对于有 n 个节点的图,两两之间的关系一共有 n(n-1)/2 种,5个节点共有10种关系,还需要知道 10-7 = 3 种关系。

可以利用 bitset 运算,将每个节点都用一个 bitset 来表述。

bitset<maxn> p[maxn]; // maxn 表示位数,p[] 表示二进制数组

初始化时候,p[i][i]=1,即 p[i] 的第 i 位为1(从右侧数第0位,第1位,第2位)。
输入 1-5,让 p[1][5] = 1(第1头牛产奶量大于第5头),则 p[1]=...100010

输入 1-4,让 p[1][4] = 1(第1头牛产奶量大于第4头),则 p[1]=...110010

输入 2-1,让 p[2][1] = 1(第2头牛产奶量大于第1头),则 p[2]=...000110

输入 2-3,让 p[2][3] = 1(第2头牛产奶量大于第3头),则 p[2]=...001110

输入 3-4,让 p[3][4] = 1(第3头牛产奶量大于第4头),则 p[3]=...011000

判断每个数组的每一位,存在如下逻辑

if(p[i][j]){
    p[i] = p[i]|p[j]; // 按位或运算,i 奶牛的产奶量大于 j 奶牛的产奶量,所以 j 奶牛和其他奶牛的产奶关系可以传递给 i,所以用或关系
}

例如:p[2][1]=1,则 p[2]=p[2]|p[1]=001110|110010=111110,奶牛2和奶牛1有关系,则奶牛1的关系传递给奶牛2。

通过此方法,可以找到每个点和其他点的关系。用 ans 累计每个数组元素 1 的个数,因为初始化时自己到自己为1,所以多算了 n 种关系,需要减去。

四 代码

package graph;

import java.util.BitSet;
import java.util.Scanner;

public class POJ3275 {
    public static void main(String[] args) {
        int n, m;
        Scanner scanner = new Scanner(System.in);
        // n 头牛
        n = scanner.nextInt();
        // m 个关系
        m = scanner.nextInt();
        
        BitSet p[] = new BitSet[n + 1];
        for (int i = 1; i <= n; i++) {
            p[i] = new BitSet(n + 1);
        }

        for (int i = 1; i <= n; i++)
            p[i].set(i);
        while (m-- != 0) {
            int u, v;
            u = scanner.nextInt();
            v = scanner.nextInt();
            p[u].set(v);
        }
        for (int k = 1; k <= n; k++)
            for (int i = 1; i <= n; i++)
                if (p[i].get(k))
                    p[i].or(p[k]);
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (p[i].get(j)) {
                    ans++;
                }
            }
        }
        System.out.println(n * (n - 1) / 2 - ans + n);
    }
}

五 测试

绿色为输入,白色为输出

CSDN 社区图书馆,开张营业!

深读计划,写书评领图书福利~

相关文章