2015多校训练第二场 hdu5305

        把这题想复杂了,一直在考虑怎么快速的判断将选的边和已选的边无冲突,后来经人提醒发现这根本没必要,反正数据也不大开两个数组爆搜就OK了,搜索之前要先排除两种没必要搜的情况,这很容易想到,爆搜的时候注意几个小细节就可以了(代码代码注释中已标好)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<utility>
using namespace std;
typedef pair<int,int> P;

vector<int> gt[30];
int g[36][36];
int c0[36],c1[36];
int count;
int n,m;
void dfs(int x,int y)
{
    if(x>n)
    {
        count++;
//        printf("%d\n",count);
        return;
    }
    else if(y>n)
    {
        if(c0[x]!=c1[x]) return;
        dfs(x+1,x+2);   //  注意这里不是从1开始  原因很简单 因为前面的都已经标记过了
    }
    else
    if(g[x][y])
    {
        c0[x]++;
        c0[y]++;    //  注意这里是y  把一条边划分之后,两个点都被划分了
        dfs(x,y+1);
        c0[x]--;
        c0[y]--;

        c1[x]++;
        c1[y]++;
        dfs(x,y+1);
        c1[x]--;
        c1[y]--;
    }
    else if(g[x][y]==0) dfs(x,y+1);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        count=0;
        scanf("%d%d",&n,&m);
        memset(g,0,sizeof(g));
        memset(c1,0,sizeof(c1));
        memset(c0,0,sizeof(c0));
        for(int k=1;k<=n;k++)
           gt[k].clear();
        for(int i=0;i<m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            gt[a].push_back(b);
            gt[b].push_back(a);
            g[a][b]=g[b][a]=1;
        }
        int f=0;
        for(int j=1;j<=n;j++)
        {
            if(gt[j].size()%2) f=1;
        }
        if(f||m%2)
        {
            printf("0\n");
            continue;
        }
        dfs(1,2);   //  0 代表 网络  1代表现实
        printf("%d\n",count);
    }
}

 

,无脑不许想太多、、、、

 

你可能感兴趣的:(2015多校训练第二场 hdu5305)