题目链接: HDU 6152 - Friend-Graph
题目大意
一个团队如果有三个以上的人两两之间不是朋友或两两之间是朋友, 那这个团队是坏团队
思路
赛后才知道有这么一个定理:6个人必然有3个互相认识或者3个互不相识(组合数学,Ramsey定理)。。。书读的还是太少,吃了没文化的亏,用dfs瞎写了这么久,不过好歹AC了
dfs, u为当前节点, f为u的上一个节点, 循环遍历u的所有儿子v, 如果v和f直接有边相连, 那就存在三个人两两之间是朋友
两两直接不是朋友的就是把原来那张图反向, 用同样的方法解决
因为如果有三个以上的人两两是朋友, 这些人中任意三个人肯定也是两两互为朋友的, 所以只要找三个的就好了
五个小时的比赛神智都不清了
代码
#include <bits/stdc++.h>
using namespace std;
const int maxv = 3500;
bool g[maxv][maxv];
int V;
void add_edge(int u, int v)
{
g[u][v] = g[v][u] = 1;
}
bool vist[maxv], flag;
void dfs(int u, int f)
{
vist[u] = 1;
for(int v=1; v<=V; ++v)
{
if(g[u][v] && v!=f)
{
if(g[v][f])
{
flag = 1;
return;
}
if(!vist[v]) dfs(v, u);
}
if(flag) return;
}
}
int main()
{
int T;
for(scanf("%d", &T); T; --T)
{
scanf("%d", &V);
memset(g, 0, sizeof(g));
for(int i=1; i<=V; ++i)
{
for(int j=1; j<=V-i; ++j)
{
int t;
scanf("%d", &t);
if(t) add_edge(i, i+j);
}
}
flag = 0;
memset(vist, 0, sizeof(vist));
for(int i=1; i<=V; ++i) if(!vist[i] && flag == 0) dfs(i, 0);
if(flag) printf("Bad Team!\n");
else
{
memset(vist, 0, sizeof(vist));
for(int i=1; i<=V; ++i)
{
for(int j=1; j<=V; ++j)
{
if(i!=j) g[i][j] = !g[i][j];
}
}
for(int i=1; i<=V; ++i) if(!vist[i] && flag == 0) dfs(i, 0);
if(flag) printf("Bad Team!\n");
else printf("Great Team!\n");
}
}
return 0;
}