您的位置:首页 > 其它

UVALive 7043 字典树+DFS

2017-08-15 21:23 253 查看

题意

分配子网,给一个子网地址,求出除了这个子网地址以外的所有子网地址。

题解

裸的字典树。只不过在子网地址记录上有一些技巧,因为子网地址恰好可以用32位整数表示,所以可以用一个unsigned int 进行状态压缩,这样就不用去搞字符串进行记录了。ORZ。。

至于寻找子网地址,在字典树上进行DFS,如果某个节点的子节点都不存在(比如说字典树为空的情况),那么就记录这个节点的状态。如果某个节点的某个子节点不存在,那么就记录这个子节点的状态。在函数开始的时候对已经存在的状态进行过滤判断,如果当前访问的子网节点是已经分配的子网节点,直接return就可以了。

代码

#include<bits/stdc++.h>
#define Ll long long
const int mod =1000000007;
#define UP(i,a,b) for(int i=a;i<b;i++)
#define DOWN(i,b,a) for(int i=b-1;i>=a;i--)
#define MEM(a,b) memset(a,b,sizeof(a))
#define W(i) while(i)
#define UINT unsigned int
using namespace std;

int ch[1100000][2],val[1100000];
int num[32];
int sz,len;
int anspos;
UINT ans[1100000],anslen[1100000];

void insert()

{
int u=0;
UP(i,0,len) {
int x=num[i];
if(!ch[u][x]) {
ch[u][x]=sz++;
}
u=ch[u][x];
}
val[u]=1;
}

void dfs(int u,UINT num,int deep) {
if(val[u]) {
return ;
}
if(!ch[u][0]&&!ch[u][1]) {
ans[anspos]=num;
anslen[anspos++]=deep;
//        cout<<deep<<endl;
return ;
}
if(ch[u][0]) {
dfs(ch[u][0],num,deep+1);
} else {
ans[anspos]=num;
anslen[anspos++]=deep+1;
}
if(ch[u][1]) {
dfs(ch[u][1],num|(1U<<(31-deep)),deep+1);
} else {
ans[anspos]=num|(1U<<(31-deep));
anslen[anspos++]=deep+1;
}
}

int main()

{
int t;
scanf("%d",&t);
int ks=1;
W(t--)
{
MEM(ch,0);
MEM(val,0);
MEM(ans,0);
MEM(anslen,0);
sz=1;
anspos=0;
int n;
scanf("%d",&n);
UP(i,0,n) {
int x;
UP(j,1,5) {
scanf("%d%*c",&x);
UP(k,1,9) {
num[j*8-k]=x%2;
//                    cout<<x%2<<" "<<(j*8-k)<<endl;
x/=2;
}
}
scanf("%d",&len);
insert();
}
//        cout<<ch[0][0]<<" "<<ch[0][1]<<endl;
dfs(0,0,0);
printf("Case #%d:\n",ks++);
printf("%d\n",anspos);
UP(i,0,anspos){
int a[4];
DOWN(j,4,0){
a[j]=ans[i]&((1<<8)-1);
ans[i]=ans[i]>>8;
}
UP(i,0,4){
if(i==3){
printf("%u/",a[i]);
}else{
printf("%u.",a[i]);
}
}
printf("%u\n",anslen[i]);
}
}
}

/*
5
1
255.255.255.128/25
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: