1. 程式人生 > >Gym - 100548I International Collegiate Routing Contest 字典樹

Gym - 100548I 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

題解:題意不太好理解,實際上就是一個二叉樹,每個數寫成2進位制 32位的,這個可以用bitset轉化,非常好用,規定長度的節點為可利用的,他的子代也可利用,所以我們找到那些最先不可利用節點就好,字典樹解決

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=32*30000;
int l[N],r[N],root[N],cnt;
int n,m;
bitset<32> bit;
vector<pair<bitset<32>, int> > ans;
void init()
{
    memset(root,0,sizeof(root));
    memset(l,-1,sizeof(l));
    memset(r,-1,sizeof(r));
    cnt=1;
    ans.clear();
}
void insert(bitset<32> b,int deep,int M_deep,int rt)
{
    if(deep==M_deep+1)
    {
        root[rt]=1;
        return;
    }
    if(b[32-deep]==0)
    {
        if(l[rt]==-1) l[rt]=++cnt;
        insert(b,deep+1,M_deep,l[rt]);
    }
    else
    {
        if(r[rt]==-1) r[rt]=++cnt;
        insert(b,deep+1,M_deep,r[rt]);
    }
}
void query(int deep,int rt)
{
    if(rt==-1)
    {
        ans.push_back(make_pair(bit,deep-1));
        return;
    }
    if(root[rt]) return;
    bit[32-deep]=1;
    query(deep+1,r[rt]);
    bit[32-deep]=0;
    query(deep+1,l[rt]);
}
int main()
{
    int T,a[5],nn=1;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d.%d.%d.%d/%d",&a[0],&a[1],&a[2],&a[3],&a[4]);
            ll tmp=0;
            for(int j=0;j<4;j++)
                tmp=tmp*256+a[j];
            bitset<32> b(tmp);
            insert(b,1,a[4],1);
        }
        printf("Case #%d:\n",nn++);
        if(n==0) printf("1\n0.0.0.0/0\n");
        else
        {
            query(1,1);
            printf("%d\n",ans.size());
            for(int i=0;i<ans.size();i++)
            {

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

        }
    }
    return 0;
}