题解
3个点(含)及以下的显然不行,
2条边(含)及以下的显然不行,
没有3种颜色的显然不行,
剩下的一定可以。
思路来源
出题方题解
1.连通图才有生成树,所以要先判图是否连通
2.图中需要出现至少一条R边,一条G边,一条B边
3.生成树的边数>=3 (R*1+G*1+B*1),所以n>=4
不考虑重边和自环,满足以上三个条件的图一定有解
证明:图连通,可以先随便造一颗普通的生成树,对于这颗生成树
(1)若已经含有三种颜色的边,则构造完毕
(2)若只有两种颜色,假如只有R边和G边,则随便找一条B边连上,这时就形成了一个环,且这个环的边数>=3,假如环上有两条以上的R边,则随便删一条R边即可,有两条以上的G边同理,
若R边和G边各只有一条,此时这是一个三元环,由于n>=4,环外肯定存在多余的R边或G边,多余R边则删环上的R边,G边同理
(3)若只有一种颜色,假如只有R边,同理先随便找一条G边连上,形成一个环,随便删一条环上的R边,就变成了情况(2)
心得
自己图论相关还是太菜了,寒假多刷题
当时6月份看prim最小证明的时候,就是用边的替换,
kruskal也是,结果现在需要用到证明相关的替换集合,反倒不会了GG
当时比赛的时候多想一下就好了,可惜卡在H上太久,
开局莽H30minWA8发已然心态爆炸,最后能抢救回来实属不易……
诶,又痛失一个beat罗老师&&吴老师的机会,痛失2K
请记住,凡是看似擦肩而过的瞬间,都是实力的巨大差距,
秦皇岛是费用流,高级组是SG函数,而这次,是最小生成树。
一个acm选手,连大一学弟和数模学长都打不过啊哎,真是菜啊
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=2e4+5;
int n,m,par[maxn];
bool color[3];
void init(int n)
{
for(int i=0;i<n;++i)
par[i]=i;
}
int find(int x)
{
return par[x]==x?x:par[x]=find(par[x]);
}
void unite(int x,int y)
{
x=find(x),y=find(y);
if(x==y)return;
if(x<y)par[y]=x;
else par[x]=y;
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m;
init(n);
for(int i=0;i<m;++i)
{
int u,v,k;
cin>>u>>v>>k;
color[k]=1;
unite(u,v);
}
bool flag=1;
int num=0;
for(int i=0;i<3;++i)if(!color[i])flag=0;
if(n<=3||m<3)flag=0;
for(int i=0;i<n;++i)if(par[i]==i)num++;
if(num>=2)flag=0;
if(!flag)puts("no");
else puts("yes");
return 0;
}