HDU 5305 Friends(DFS + 剪枝)
2017-04-20 13:28
281 查看
http://acm.hdu.edu.cn/showproblem.php?pid=5305
题目大意就是,有m对朋友,每个人可以有线上和线下朋友,对于每个人,要求线上和线下朋友数目相同。
做法:我们直接把朋友关系保存,当成边,然后DFS枚举每一条边两种情况,两人互为网友或者是线下的朋友。但是这样最高的复杂度达到了2^28,而且T等于100,这样显然是不足以在时限内解决问题的。此时想尽办法剪枝。
剪枝的地方有:1,如果有人的朋友是奇数个,则肯定不存在合理的情况,直接输出0
2,DFS的时候,枚举第x条边,但是这条边的某个端点s,他的线上朋友数已经是他自己的朋友数的一半,那么不可以把它放入线上情况递归下去。同样的,如果线下的朋友数达到了他自己朋友数的一半,也不可放入线下的情况递归下去。
代码如下:
#include<bits/stdc++.h>
using namespace std;
vector < pair<int,int> > fri;
int n, cnt, fact[15], online[15], spot[15], top[15];
void dfs(int x)
{
if(x == fri.size())
{
cnt++;
return;
}
if(online[fri[x].first] < top[fri[x].first] && online[fri[x].second] < top[fri[x].second])
{
online[fri[x].first]++;
online[fri[x].second]++;
dfs(x+1);
online[fri[x].first]--;
online[fri[x].second]--;
}
if(fact[fri[x].first] < top[fri[x].first] && fact[fri[x].second] < top[fri[x].second])
{
fact[fri[x].first]++;
fact[fri[x].second]++;
dfs(x+1);
fact[fri[x].first]--;
fact[fri[x].second]--;
}
}
int main()
{
int T,m,x,y;
cin >> T;
while(T--)
{
memset(fact,0,sizeof(fact));
memset(online,0,sizeof(online));
memset(spot,0,sizeof(spot));
fri.clear();
cnt = 0;
scanf("%d%d", &n, &m);
if(n == 1)
{
printf("1\n");
continue;
}
if(m == 0)
{
printf("1\n");
continue;
}
while(m--)
{
scanf("%d%d", &x, &y);
fri.push_back(make_pair(x,y));
spot[x]++;
spot[y]++;
}
bool flag = 1;
for(int i = 1; i <= n; i++)
{
if(spot[i] % 2 == 1)
flag = 0;
top[i] = spot[i] / 2;
}
if(flag == 0)
{
printf("0\n");
continue;
}
online[fri[0].first]++;
online[fri[0].second]++;
dfs(1);
online[fri[0].first]--;
online[fri[0].second]--;
fact[fri[0].first]++;
fact[fri[0].second]++;
dfs(1);
fact[fri[0].first]--;
fact[fri[0].second]--;
cout << cnt << endl;
}
return 0;
}
题目大意就是,有m对朋友,每个人可以有线上和线下朋友,对于每个人,要求线上和线下朋友数目相同。
做法:我们直接把朋友关系保存,当成边,然后DFS枚举每一条边两种情况,两人互为网友或者是线下的朋友。但是这样最高的复杂度达到了2^28,而且T等于100,这样显然是不足以在时限内解决问题的。此时想尽办法剪枝。
剪枝的地方有:1,如果有人的朋友是奇数个,则肯定不存在合理的情况,直接输出0
2,DFS的时候,枚举第x条边,但是这条边的某个端点s,他的线上朋友数已经是他自己的朋友数的一半,那么不可以把它放入线上情况递归下去。同样的,如果线下的朋友数达到了他自己朋友数的一半,也不可放入线下的情况递归下去。
代码如下:
#include<bits/stdc++.h>
using namespace std;
vector < pair<int,int> > fri;
int n, cnt, fact[15], online[15], spot[15], top[15];
void dfs(int x)
{
if(x == fri.size())
{
cnt++;
return;
}
if(online[fri[x].first] < top[fri[x].first] && online[fri[x].second] < top[fri[x].second])
{
online[fri[x].first]++;
online[fri[x].second]++;
dfs(x+1);
online[fri[x].first]--;
online[fri[x].second]--;
}
if(fact[fri[x].first] < top[fri[x].first] && fact[fri[x].second] < top[fri[x].second])
{
fact[fri[x].first]++;
fact[fri[x].second]++;
dfs(x+1);
fact[fri[x].first]--;
fact[fri[x].second]--;
}
}
int main()
{
int T,m,x,y;
cin >> T;
while(T--)
{
memset(fact,0,sizeof(fact));
memset(online,0,sizeof(online));
memset(spot,0,sizeof(spot));
fri.clear();
cnt = 0;
scanf("%d%d", &n, &m);
if(n == 1)
{
printf("1\n");
continue;
}
if(m == 0)
{
printf("1\n");
continue;
}
while(m--)
{
scanf("%d%d", &x, &y);
fri.push_back(make_pair(x,y));
spot[x]++;
spot[y]++;
}
bool flag = 1;
for(int i = 1; i <= n; i++)
{
if(spot[i] % 2 == 1)
flag = 0;
top[i] = spot[i] / 2;
}
if(flag == 0)
{
printf("0\n");
continue;
}
online[fri[0].first]++;
online[fri[0].second]++;
dfs(1);
online[fri[0].first]--;
online[fri[0].second]--;
fact[fri[0].first]++;
fact[fri[0].second]++;
dfs(1);
fact[fri[0].first]--;
fact[fri[0].second]--;
cout << cnt << endl;
}
return 0;
}
相关文章推荐
- HDU 5305 Friends(2015多校第二场 dfs + 剪枝)
- hdu 5305 Friends(dfs)
- HDU 5305 Friends (DFS)
- hdu 5305 Friends (dfs)
- *HDU 5305 - Friends (DFS + 剪枝)
- hdu 5305 Friends (dfs)
- HDU 5305 Friends (DFS)
- HDU 5305 Friends(DFS)
- 2015多校联合训练赛 hdu 5305 Friends 2015 Multi-University Training Contest 2 枚举+剪枝
- 【HDU 5305】Friends 多校第二场(双向DFS)
- HDU 5305 Friends dfs
- HDU 5305 Friends (DFS)
- HDU 5305 Friends(dfs)
- HDU 5305 Friends(dfs)
- HDU 5305 Friends(dfs)
- hdu(5305)——Friends(dfs)
- DFS HDU 5305 Friends
- HDU 5305 Friends (DFS,穷举+剪枝)
- hdu 5305 Friends(dfs)
- 【HDU 5305】Friends 多校第二场(双向DFS)