題目名稱:Friends
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5305
題意:給定n個人,m對朋友關係,朋友關係可以選擇online聊天,也可以選擇offline,對於每個人,他選擇的online和offline的朋友相同(比如擁有x個online,就得擁有x個offline),問全部人滿足有多少種情況?只要一個選擇不同,視爲不同情況。
思路(hdu的題解):由於總點數很少,我們考慮暴力,但總的邊數有8*7/2=28,所以會TLE,一個點的度數爲奇數時,答案肯定爲0,每個點爲偶數時,總邊數最多爲8*6/2=24,還是一個較大的數字。最後一個優化是搜索一個點到最後一條邊時不用枚舉,因爲已經確定了。也就是說搜索邊數少n-1,所以只要搜索17條邊,暴力就可以了,,
搜索他給的那些邊,然後可以爲online或者offline,最後判斷每個點的online朋友和offline朋友是否相等就行了,相等就總數加一
代碼如下:
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
int d1[10],d2[10],sum[10]; //d1表示online,d2表示offline
int n,m;
int ans=0,a[30],b[30];
int judge() //判斷online和offline相等
{
for(int i=1;i<=n;i++)
{
if(d1[i]!=d2[i])
return 0;
}
return 1;
}
void dfs(int num) //num表示第幾組關係
{
if(num==m+1)
{
if(judge())
ans++;
return ;
}
int x=a[num],y=b[num];
if((d1[x]<sum[x]/2)&&(d1[y]<sum[y]/2)) //假設該邊爲online
{
d1[x]++;
d1[y]++;
dfs(num+1);
d1[x]--; //記得修改的邊要及時修改回來
d1[y]--;
}
if((d2[x]<sum[x]/2)&&(d2[y]<sum[y]/2))
{
d2[x]++;
d2[y]++;
dfs(num+1);
d2[x]--;
d2[y]--;
}
}
int main()
{
int t;
while(scanf("%d",&t)!=EOF)
{
while(t--)
{
memset(d1,0,sizeof(d1));
memset(d2,0,sizeof(d2));
memset(sum,0,sizeof(sum));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a[i],&b[i]);
sum[a[i]]++;
sum[b[i]]++;
}
ans=0;
int ok=1;
for(int i=1;i<=n;i++) //爲奇數時說明不成立
{
if(sum[i]&1)
{
ok=0;
break;
}
}
if(ok)
{
dfs(1);
printf("%d\n",ans);
}
else
printf("0\n");
}
}
return 0;
}