UVALive

来源:互联网 发布:网络语言暴力的案例 编辑:程序博客网 时间:2024/06/03 20:04

You may know that Bluegao University (formly Bluey University) is famous of networking technology.
One day, their headmaster Yuege received a special router, along with a task about routing table.
In this problem, routing table is a (probably) big table with several items, each item represents a
subnet. The router has limited function, it can only deal with two next-hops and one main routing
table. Packets will be send to next hop A if there exists a subnet containing the destination of the
packet in the main routing table. Otherwise they will be send to next hop B.
You may know that, IPv4 uses 32-bit (four-byte) addresses, which limits the address space to
4294967296 (232) addresses. IPv4 addresses may be written in any notation expressing a 32-bit integer
value, for human convenience, they are most often written in the dot-decimal notation, which consists of
four octets of the address expressed individually in decimal and separated by periods. But their binary
notation is also very useful. For example, IP address 128.2.142.23 can be expressed in dot-binary
notation as 10000000.00000010.10001110.00010111. A subnet is a block of adjacent IP addresses
with exactly same binary prefix, and usually written as the first IP address in its address space together
with the bit length of prefix, like “202.120.224.0/24”. If an IP address is in the range of an subnet,
we say that this subnet contains the IP address.
Yuege’s task is to invert the behaviour of his router, make all packets currently routed to hop A
route to hop B, and vice versa. Also he wants to keep the size of the main routing table as small as
possible, for performance.
In short, for a given routing table (i.e. a bunch of subnets), we need to get its “complement”, i.e.
calculate a minimum set of subnets which have no intersection with given subnets, and their union
must be the whole IPv4 address space.
Remember that Bluegao University is famous of networking tech, as headmaster of Bluegao 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 of the 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 number of subnets. Next n
lines, each contains a subnet in the format of ‘a.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 IP address 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 n indicates the number of subnets in your answer. Next n lines each
line contains a subnet in the same format as input. You may output them in any order.
Sample Input
3
0
1
0.0.0.0/1
1
128.0.0.0/1
Sample Output
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树,然后进行dfs。

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<queue>#include<vector>#include<bitset>#include<algorithm>#include<map>using namespace std;typedef unsigned int UINT;const int MAXN=3e4+5;const int maxnode=1e7+5;const int sigma_size=2;vector<pair<UINT,int> > ans;struct node{    UINT mask;    int l;}subnets[MAXN];struct Trie{    int ch[maxnode][sigma_size];    bool val[maxnode];    int sz;    void init() {sz=1;memset(ch[0],0,sizeof(ch[0]));memset(val,false,sizeof(val));}    void Insert(bitset<32> b,int l)    {        int u=0;        for(int i=l-1;i>=0;i--)        {            int c=b[i];            if(!ch[u][c])            {                memset(ch[sz],0,sizeof(ch[sz]));                val[sz]=false;                ch[u][c]=sz++;            }            u=ch[u][c];        }        val[u]=true;    }    void dfs(int u,int dep,UINT now)    {        if(val[u]) return;        if(ch[u][0])        {            dfs(ch[u][0],dep+1,now<<1);            if(!ch[u][1])            {                ans.push_back(make_pair((now<<1)|1,dep+1));            }        }        if(ch[u][1])        {            dfs(ch[u][1],dep+1,(now<<1)|1);            if(!ch[u][0])            {                ans.push_back(make_pair(now<<1,dep+1));            }        }    }};Trie trie;int main(){    int T;    scanf("%d",&T);    int cas=0;    while(T--)    {        trie.init();        ans.clear();        printf("Case #%d:\n",++cas);        int n;        scanf("%d",&n);        if(n==0)        {            printf("1\n0.0.0.0/0\n");        }else        {            UINT a,b,c,d,l;            for(int i=1;i<=n;i++)            {                scanf("%u.%u.%u.%u/%u",&a,&b,&c,&d,&l);                //printf("%u %u %u %u %u\n",a,b,c,d,l);                subnets[i].mask=(a<<24)+(b<<16)+(c<<8)+d;                //printf("%d: %u\n",i,subnets[i].mask);                bitset<32> bit(subnets[i].mask);                bit>>=(32-l);                //for(int j=l-1;j>=0;j--) cout<<bit[j];                //cout<<endl;                trie.Insert(bit,l);            }            trie.dfs(0,0,0);            int sz=ans.size();            printf("%d\n",sz);            UINT tmp;            bool fst;            for(int i=0;i<sz;i++)            {                tmp=ans[i].first;                //cout<<"tmp: "<<tmp<<endl;                //cout<<"l: "<<ans[i].second<<endl;                tmp<<=(32-ans[i].second);                //cout<<"tmp: "<<tmp<<endl;                fst=true;                for(int j=3;j>=0;j--)                {                    if(!fst) printf(".");                    else fst=false;                    printf("%u",(tmp>>(8*j))&255);                }                printf("/%d\n",ans[i].second);            }        }    }    return 0;}/*100010.0.0.0/11128.0.0.0/1148.0.0.0/4*/