代码改变世界

【HDU 5305】Friends 多校第二场(双向DFS)

2017-05-09 15:19  tlnshuju  阅读(339)  评论(0编辑  收藏  举报

依据题意的话最多32条边,直接暴力的话 2 ^ 32肯定超时了。我们能够分两次搜索时间复杂度降低为 2 * 2  ^ 16

唯一须要注意的就是对眼下状态的哈希处理。

我採用的是 十进制表示法

跑的还是比較快的,可能是用STL函数的原因添加了一些常数复杂度。

#include<map>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> pill;
const int maxn = 55;
struct Edge{
    int a,b;
}edge[maxn];
int n,m;
LL cnt,base[15];
int _count[15];
map<pill,int>vis;
void init(){
    base[1] = 1;
    for(int i = 2; i < 10; i++)
        base[i] = base[i - 1] * 10;
}
void calc(int state1,int state2,int &a,int &b){
    int base = 1;
    for(int i = 1; i <= n; i++){
        int d1 = state1 % 10, d2 = state2 % 10;
        int v1 = _count[i] - d1, v2 = _count[i] - d2;
        a += base * v1;
        b += base * v2;
        base *= 10;
        state1 /= 10;
        state2 /= 10;
    }
}
void dfs1(int now,int finish,int state1,int state2){
    if(now == finish){
        vis[make_pair(state1,state2)] ++;
        return;
    }
    int a = edge[now].a, b = edge[now].b;
    dfs1(now + 1,finish,state1 + base[a] + base[b],state2);
    dfs1(now + 1,finish,state1,state2 + base[a] + base[b]);
}
void dfs2(int now,int finish,int state1,int state2){
    if(now == finish){
        int x = 0,y = 0;
        calc(state1,state2,x,y);
        if(x >= 0 && y >= 0)
            cnt += vis[make_pair(x,y)];
        return;
    }
    int a = edge[now].a, b = edge[now].b;
    dfs2(now + 1,finish,state1 + base[a] + base[b],state2);
    dfs2(now + 1,finish,state1,state2 + base[a] + base[b]);
}
int main(){
    int T;
    init();
    scanf("%d",&T);
    while(T--){
        vis.clear();
        memset(_count,0,sizeof(_count));
        scanf("%d%d",&n,&m);
        for(int i = 0; i < m; i++){
            scanf("%d%d",&edge[i].a,&edge[i].b);
            _count[edge[i].a] ++;
            _count[edge[i].b] ++;
        }
        int ok = 1;
        for(int i = 1; i <= n; i++){
            if(_count[i] % 2 != 0){
                ok = 0;
                break;
            }
            _count[i] /= 2;
        }
        cnt = 0;
        if(ok){
            dfs1(0,m / 2,0,0);
            dfs2(m / 2,m,0,0);
        }
        printf("%d\n",cnt);
    }
    return 0;
}