题目大意:
给你一些子网,求它们在整个网段的补集。
思路:
将子网转换成二进制建一棵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 }