您的位置:首页 > 其它

hdu 5305 回溯+剪枝

2015-07-23 20:48 357 查看
思路:对每一条边涂上颜色1或-1,颜色值加到关联的两个点上,则一种成功的方案必须满足最后每个点的值为0.

剪枝:统计出和某个点i相关联的边的个数,如果枚举到某一条边的时候发现:abs(sum[i]) > degree[i],则剪去,其中sun[i]表示i点的值,degree[i]表示剩下的还没有枚举的和i关联的边的个数。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

const int N = 9;
const int M = 28;
int sum
;
int degree
;
int n, m, ans;

struct Edge
{
int u, v;
} edge[M];

int judge()
{
for ( int i = 1; i <= n; i++ )
{
if ( sum[i] ) return 0;
}
return 1;
}

int abs( int x )
{
return x > 0 ? x : -x;
}

void dfs( int cur )
{
if ( cur == m )
{
ans += judge();
return ;
}
for ( int i = 1; i <= n; i++ )
{
if ( abs(sum[i]) > degree[i] ) return ;
}
int u = edge[cur].u, v = edge[cur].v;
degree[u]--;
degree[v]--;
sum[u]++;
sum[v]++;
dfs( cur + 1 );
sum[u]--;
sum[v]--;
sum[u]--;
sum[v]--;
dfs( cur + 1 );
sum[u]++;
sum[v]++;
degree[u]++;
degree[v]++;
}

int main ()
{
int t;
scanf("%d", &t);
while ( t-- )
{
scanf("%d%d", &n, &m);
memset( degree, 0, sizeof(degree) );
for ( int i = 0; i < m; i++ )
{
scanf("%d%d", &edge[i].u, &edge[i].v);
degree[edge[i].u]++;
degree[edge[i].v]++;
}
bool flag = false;
for ( int i = 1; i <= n; i++ )
{
if ( degree[i] & 1 )
{
flag = true;
break;
}
}
ans = 0;
if ( !flag )
{
memset( sum, 0, sizeof(sum) );
dfs(0);
}
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: