HDU 4760 Good Firewall ( Trie树 )

一开始看的时候就想歪了,比赛的时候一直在YY线段树区间覆盖,然后纠结节点数太多开不下怎么办啊啊啊啊……

然后昨天吃饭的时候也在纠结这到底是个啥题,后来发现公共前缀->前缀??!!!!->这不是很显然的Trie么……QAQ

举例说明:

对于subnet: 123.45.4.0/22,转化成二进制后,取前22位(长度由子网掩码决定)加入Trie树,后面的IP一定是0所以无意义,然后每个节点开一个vector保存能到达这个节点的所有子网的Pid,以及该子网IP的最大值。

对于ip_src:查找它所属于的所有子网组的Pid,并标记出来。

对于ip_dst:看它与ip_src所属的所有子网组的Pid跟之前标记出来的是否有相同的,如果有,就证明他俩在同一个子网组中。

PS.昨天晚上在杭电交一直RERERERE,改到大半夜……今天早上又看了一遍还是觉得代码没错,原样交上竟然A了……杭电你还我青春啊啊啊!!!

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>

#define LL long long int

using namespace std;

const int MAXN = 1028;

struct IP
{
    int id;
    LL num;
    IP( int id, LL num ): id(id), num(num) { }
};

struct node
{
    node *next[2];
    vector<IP> R;
    node()
    {
        next[0] = next[1] = NULL;
        R.clear();
    }
};

node *root;
bool ok[MAXN];
int ans[MAXN];
int cas;

void Insert( int mask, LL ip, int id ) { node *p = root; for ( int i = 0; i < mask; ++i ) { int id = ( ( ip >> (31 - i) ) & 1 ) == 1 ? 1 : 0; if ( p->next[id] == NULL ) { p->next[id] = new node; } p = p->next[id]; } p->R.push_back( IP( id, ip ) ); return; } LL ReadIP() { int a, b, c, d; scanf( "%d.%d.%d.%d", &a, &b, &c, &d ); LL res = 0; res |= (LL)a, res <<= 8; res |= (LL)b, res <<= 8; res |= (LL)c, res <<= 8; res |= d; return res; } void FindSRC( LL ip ) { node *p = root; for ( int i = 0; i < 32; ++i ) { int id = ( ( ip >> (31 - i) ) & 1 ) == 1 ? 1 : 0; int sz = p->R.size(); for ( int j = 0; j < sz; ++j ) { if ( ok[ p->R[j].id ] && ( ip&( ( (1LL << (31-i)) - 1 )) ) <= p->R[j].num ) ans[ p->R[j].id ] = cas; } if ( p->next[id] == NULL ) return; p = p->next[id]; } return; } bool FindDST( LL ip ) { node *p = root; for ( int i = 0; i < 32; ++i ) { int id = ( ( ip >> (31 - i) ) & 1 ) == 1 ? 1 : 0; int sz = p->R.size(); for ( int j = 0; j < sz; ++j ) { if ( ok[ p->R[j].id ] && (ip&( ( (1LL << (31-i)) - 1 )) ) <= p->R[j].num ) { if ( ans[ p->R[j].id ] == cas ) return true; } } if ( p->next[id] == NULL ) return false; p = p->next[id]; } return false; } int main() { //freopen( "in.txt", "r", stdin ); //freopen( "out.txt", "w", stdout ); char op[4]; root = new node; memset( ok, false, sizeof(ok) ); cas = 0; while ( scanf( "%s", op ) == 1 ) { if ( op[0] == 'E' ) { int id; scanf( "%d", &id ); ok[id] = true; int n; scanf( "%d", &n ); for ( int i = 0; i < n; ++i ) { int mask; LL ip = ReadIP(); scanf( "/%d", &mask ); ip += ( 1LL << (32 - mask) ) - 1; Insert( mask, ip, id ); } } else if ( op[0] == 'D' ) { int id; scanf( "%d", &id ); ok[id] = false; } else { ++cas; LL IPsrc = ReadIP(); FindSRC( IPsrc ); LL IPdst = ReadIP(); if ( FindDST( IPdst ) ) puts("F"); else puts("D"); } } return 0; }

 

posted @ 2013-09-29 09:06  冰鸮  阅读(475)  评论(0编辑  收藏  举报