2014 西安站 I International Collegiate Routing Contest(trie)

来源:互联网 发布:数据抓取软件 编辑:程序博客网 时间:2024/06/01 17:52

题目链接:这里

题意:输入IPv4地址空间中的一些子网号,构成一个网络集合。
输出最小的一个网络集合,要求其与输入集合没有交集,且相对IPv4地址空间全集,是输入集合的补集。输出集合包含的子网号,格式遵循网络规范
做法:tire树,把所有输入的子网插入trie里面,然后遍历一下,如果一个结点的左儿子和右儿子有一个是标记过的,就输出没有标记的那个儿子的子网。

#include <bits/stdc++.h>using namespace std;#define pii pair<int, int>#define MP make_pair#define LL long long#define ls (i << 1)#define rs (ls | 1)#define md (ll + rr >> 1)#define lson ll, md, ls#define rson md + 1, rr, rs#define eps 1e-8#define inf 0x3f3f3f3f#define mod 1000000007#define N 100010#define M 200020#define fi first#define se secondchar buf[32000000],*pt = buf,*o = buf;int getint(){    int f = 1,x = 0;    while((*pt != '-') && (*pt < '0' || *pt > '9'))    pt ++;    if(*pt == '-')    f = -1,pt ++;    else    x = *pt++ - 48;    while(*pt >= '0' && *pt <= '9')    x = x * 10 + *pt ++ - 48;    return x * f;}char getch(){    char ch;    while(*pt < 'A' || *pt > 'Z')    pt ++;    ch=*pt;pt++;    return ch;}int ch[N*30][2], cnt, tot, n;bool vis[N*30];pair<LL, int> p[N];int insert(LL v, int k){    int u = 1;    for(int i = 31; i >= 0 && k; --i, --k){        int c = v >> i & 1;        if(!ch[u][c]){            ch[u][c] = ++tot;            memset(ch[tot], 0, sizeof ch[tot]);            vis[tot] = 0;        }        u = ch[u][c];    }    vis[u] = 1;}void print(LL v, int dep){    v <<= dep;    int a = v >> 24;    v ^= (LL)a << 24;    int b = v >> 16;    v ^= (LL)b << 16;    int c = v >> 8;    v ^= (LL)c << 8;    int d = v;    printf("%d.%d.%d.%d/%d\n", a, b, c, d, 32 - dep);}int query(int u, LL x, int dep){    if(u == 0 || vis[u]) return vis[u];    if(dep == -1)        return vis[u];    int p1 = query(ch[u][0], x << 1, dep - 1);    int p2 = query(ch[u][1], x << 1 | 1, dep - 1);    if(p1 && !p2){        p[cnt++] = MP(x << 1 | 1, dep);    }    else if(!p1 && p2){        p[cnt++] = MP(x << 1, dep);    }    return p1 | p2;}int main(){    int cas, kk = 0;    scanf("%d", &cas);    while(cas--){        scanf("%d", &n);        tot = 1;        memset(ch[tot], 0, sizeof ch[tot]);        memset(ch[0], 0, sizeof ch[0]);        vis[0] = vis[1] = 0;        for(int i = 0; i < n; ++i){            int a, b, c, d, k;            scanf("%d.%d.%d.%d/%d", &a, &b, &c, &d, &k);            LL v = 1LL * a * (1 << 24) + b * (1 << 16) + c * (1 << 8) + d;            insert(v, k);        }        printf("Case #%d:\n", ++kk);        if(n == 0){            printf("1\n0.0.0.0/0\n"); continue;        }        cnt = 0;        query(1, 0LL, 31);        printf("%d\n", cnt);        for(int i = 0; i < cnt; ++i)            print(p[i].fi, p[i].se);    }    return 0;}
0 0