CF GYM 100548 International Collegiate Routing Contest(2014ACM西安现场赛Problem I)

ProblemI. International Collegiate Routing Contest


Description

You may know thatBluegao University (formly Bluefly University) is famous ofnetworking technology. One day, their headmaster Yuege received aspecial router, along with a task about routing table.

In this problem,routing table is a (probably) big table with several items, each itemrepresents a subnet. The router has limited function, it can onlydeal with two next-hops and one main routing table. Packets will besend to next hop A if there exists a subnet containing thedestination of the packet in the main routing table. Otherwise theywill be send to next hop B.

You may know that,IPv4 uses 32-bit (four-byte) addresses, which limits the addressspace to 4294967296 (2^32) addresses. IPv4 addresses may be writtenin any notation expressing a 32-bit integer value, for humanconvenience, they are most often written in the dot-decimal notation,which consists of four octets of the address expressed individuallyin decimal and separated by periods. But their binary notation isalso very useful. For example, IP address 128.2.142.23 can beexpressed in dot-binary notation as10000000.00000010.10001110.00010111.

A subnet is a blockof adjacent IP addresses with exactly same binary prefix, and usuallywritten as the first IP address in its address space together withthe bit length of prefix, like “202.120.224.0/24”. If an IPaddress is in the range of an subnet, we say that this subnetcontains the IP address.

Yuege’s task isto invert the behaviour of his router, make all packets currentlyrouted to hop A route to hop B, and vice versa. Also he wants to keepthe size of the main routing table as small as possible, forperformance.

In short, for agiven routing table (i.e. a bunch of subnets), we need to get its“complement”, i.e. calculate a minimum set of subnets which haveno intersection with given subnets, and their union must be the wholeIPv4 address space.

Remember thatBluegao University is famous of networking tech, as headmaster ofBluegao University, Yuege definitely knows how to solve such problem,but he is too lazy to code, so he turns to you for help.


Input

The first line ofthe input gives the number of test cases, T. T test cases follow.

For each test case,the first line contains an integer n (0 ≤ n ≤ 30000), the numberof subnets. Next n lines, each contains a subnet in the format ofa.b.c.d/l, a, b, c, d, l are all integers, 0 ≤ a, b, c, d < 256,0 ≤ l ≤ 32.

Note that even if l= 32, the “/32” part should not be omitted. And if l = 0, the IPaddress part must be “0.0.0.0”.


Output

For each test case,first output one line “Case #x:”, where x is the case number(starting from 1). Then on the second line print an integer nindicates the number of subnets in your answer. Next n lines eachline contains a subnet in the same format as input. You may outputthem in any order.


Samples

Sample Input

Sample Output

3

0

1

0.0.0.0/1

1

128.0.0.0/1

Case #1:

1

0.0.0.0/0

Case #2:

1

128.0.0.0/1

Case #3:

1

0.0.0.0/1



知识点:

Trie树,二进制。

题目大意:

输入IPv4地址空间中的一些子网号,构成一个网络集合。

输出最小的一个网络集合,要求其与输入集合没有交集,且相对IPv4地址空间全集,是输入集合的补集。输出集合包含的子网号,格式遵循网络规范。


解题思路:

每个IP地址由32位二进制组成。整个地址空间可以表现为一棵二叉树(简化的Trie树),如下图所示:











图中表示的是以下4个子网的覆盖情况:

0.0.0.0/1 (二进制前1位是0

32.0.0.0/3(二进制前3位是001

128.0.0.0/2 (二进制前2位是10

224.0.0.0/3 (二进制前3位是111

图中的红色节点代表网络覆盖的终结点,这一网络号覆盖红色节点下的完整一支;黄色节点也是包含在这个网络中的,

题目要求的就是树上没有被输入集合覆盖的分支。不能与红、黄节点有任何覆盖。


建立Trie树后,DFS遍历树上的分支,输出没有被覆盖的分支即可。


实现技巧:

使用bitset,简化十进制与二进制的转换。



参考代码:

#include <iostream>
#include <cstring>
#include <bitset>
#include <cstdio>
#include <vector>
using namespace std;

const int MAXN = 500010;
int n, nCase, cCase;
bool value[MAXN], root[MAXN];
int L[MAXN], R[MAXN], cnt;
bitset<32> bit(0);
vector<pair<bitset<32>, int> > ans;

void init() {
    memset(value, false, sizeof(value));
    memset(root, false, sizeof(root));
    memset(L, -1, sizeof(L));
    memset(R, -1, sizeof(R));
    cnt = 1;
    ans.clear();
}

void insert(const bitset<32> &bit_ip, int deep, int max_deep, int rt) {
    value[rt] = true;
    if (deep == max_deep) {
        root[rt] = true;
        return;
    }
    if (!bit_ip[32-deep-1]) {
        if (L[rt] == -1) L[rt] = ++cnt;
        insert(bit_ip, deep+1, max_deep, L[rt]);
    } else {
        if (R[rt] == -1) R[rt] = ++cnt;
        insert(bit_ip, deep+1, max_deep, R[rt]);
    }
}

void query(int deep, int rt) {
    if (root[rt]) return;
    if (rt == -1) {
        ans.push_back(make_pair(bit, deep));
        return;
    }
    bit[32-deep-1] = 1;
    query(deep+1, R[rt]);
    bit[32-deep-1] = 0;
    query(deep+1, L[rt]);
}

void input() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        int a[15];
        scanf("%d.%d.%d.%d/%d", &a[0], &a[1], &a[2], &a[3], &a[4]);

        long long ip = 0;
        for (int j = 0; j < 4; j++) {
            ip = (ip * 256) + a[j];
        }
        bitset<32> bit_ip(ip);
        insert(bit_ip, 0, a[4], 1);
    }
}

void solve() {
    printf("Case #%d:\n", ++cCase);
    if (n == 0) {
        printf("1\n0.0.0.0/0\n");
        return;
    }

    query(0, 1);

    printf("%d\n", ans.size());
    for (int k = 0; k < ans.size(); k++) {
        for (int i = 3; i >= 0; i--) {
            int a = 0;
            for (int j = 7; j >= 0; j--) {
                a = a * 2 + ans[k].first[i*8+j];
            }
            printf("%d", a);
            if (i) printf(".");
        }
        printf("/%d\n", ans[k].second);
    }
}

int main() {
    scanf("%d", &nCase);
    while (nCase--) {
        init();
        input();
        solve();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值