BNUOJ48605International Collegiate Routing Contest 题解

题目大意:

  给你一些子网,求它们在整个网段的补集。

思路:

  将子网转换成二进制建一棵Trie,直接DFS搜到没有了就记下来输出。注意:所给的子网会有交集,若搜到结尾就不向下搜了。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #define M 40000
 6 using namespace std;
 7 int cnt,num,a[60],flag[M<<5],trie[M<<5][9];
 8 struct node { int len; int d[9]; }ans[M<<5];
 9 
10 int read()
11 {
12     int x=0;
13     char ch=getchar();
14     while (ch<'0' || ch>'9') ch=getchar();
15     while (ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
16     return x;
17 }
18 
19 void wk(int x,int y)
20 {
21     for  (int l=8;l;l--,x/=2) a[l+(y<<3)]=x%2;
22 }
23 
24 void ins(int l)
25 {
26     int now=0,i,j;
27     for (i=1;i<=l;now=trie[now][a[i]],i++)
28         if (!trie[now][a[i]]) trie[now][a[i]]=++cnt;
29     flag[now]=1;
30 }
31 
32 void sa(long long x,int l)
33 {
34     ans[++num].len=l; int i,k=1;
35     for (i=l;i;i--,x>>=1) a[i]=x%2;
36     ans[num].d[1]=ans[num].d[2]=ans[num].d[3]=ans[num].d[4]=0;
37     for (i=1;i<=l;i++)
38     {
39         ans[num].d[k]=(ans[num].d[k]<<1)+a[i];
40         if (i%8==0) k++;
41     }
42     if (l%8) ans[num].d[k]<<=(8-l%8);
43 }
44 
45 void dfs(int k,long long x,int l)
46 {
47     if (flag[k]) return;
48     if (trie[k][0])
49         if (trie[k][1]) dfs(trie[k][0],x<<1,l+1),dfs(trie[k][1],x<<1|1,l+1);
50         else sa(x<<1|1,l+1),dfs(trie[k][0],x<<1,l+1);
51     else if (trie[k][1]) sa(x<<1,l+1),dfs(trie[k][1],x<<1|1,l+1);
52 }
53 
54 int main()
55 {
56     int t=read(),ii;
57     for (ii=1;ii<=t;ii++)
58     {
59         int n=read(),i,j;
60         memset(trie,0,sizeof(trie));
61         memset(flag,0,sizeof(flag));
62         for (i=1;i<=n;i++)
63         {
64             int u=read(),v=read(),w=read(),x=read();
65             wk(u,0),wk(v,1),wk(w,2),wk(x,3),ins(read());
66         }
67         num=0,dfs(0,0,0);
68         printf("Case #%d:
",ii);
69         if (!n) printf("1
0.0.0.0/0
");
70         else
71         {
72             printf("%d
",num);
73             for (i=1;i<=num;i++) printf("%d.%d.%d.%d/%d
",ans[i].d[1],ans[i].d[2],ans[i].d[3],ans[i].d[4],ans[i].len);
74         }
75     }
76     return 0;
77 }
我一直在繁华的苍凉中徘徊着,用一颗OI的心寻找着生命和宇宙的美妙与玄奥。
原文地址:https://www.cnblogs.com/HHshy/p/5754355.html