这道题目的意思的解释解释:
题目给出n个节点,m条边(小于n*n,使得n个节点都连通),k值。要求我们判断能否只用k条蓝色边(外加给定的任意条红色边)使得所有节点形成一个生成树(n-1条边把n个节点全部连起来)
题解:
在比赛的时候想出了一个错误的做法= =!结果一下午WA……
正确的是将蓝边和红边分别跑一边最小生成树(Kruscal算法),跑的时候记录有多少条边加了进来。
设counter_r为加进来的红边,counter_b为加进来的蓝边
则当k>=n-1- counter_r && k<= counter_b的时候便满足要求;
n-1-counter_r表示还需要至少这么多条蓝边才能构成生成树。(下限)如果k比这个还小的话,就没有足够的R可以使得整个图构成一个生成树。
counter_b则表示可以同时加进来的蓝边的最大个数。(上限)
对于介于上限与下限之间的k值:
若增大,即加多一条蓝边,则会产生环,这时候则可以删除一条多余的红边。
若减少,即减少一条蓝边,仍可以找到一条红边替代它的位置使整个图保持生成树的结构。
唔……其实思路是我同学告诉我的= =,也不知道有没有说清楚,若有其他理解,望留言告之楼主……
另外……Ps一则找不到结构体哪里出错的代码,求有心的同学发现之…………http://zhidao.baidu.com/question/469243984.html?quesup2
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxx = 1010;
int Find(int x,int father[])
{
while(x!=father[x]) x = father[x];
return x;
}
void Union(int r1, int r2, int& counter,int father[])
{
int a = Find(r1,father);
int b = Find(r2,father);
if(a!=b)
{
counter++;
father[a] = b;
}
}
void ini(int n,int father[])
{
for(int i=1; i<=n; i++)
father[i] = i;
}
int main()
{
// freopen("1007.txt","r",stdin);
int n,m,k;
int father_r[maxx];
int father_b[maxx];
while(scanf("%d %d %d",&n,&m,&k),n||m||k)
{
ini(n,father_r);
ini(n,father_b);
int counter_r,counter_b;
counter_r = counter_b = 0;
for(int i=1; i<=m; i++)
{
char ch=0;
while(ch!='B'&&ch!='R')
ch=getchar();
int u,v;
scanf("%d%d",&u,&v);
if(ch=='B')
Union(u,v,counter_b,father_b);
else
Union(u,v,counter_r,father_r);
}
if(k<=counter_b && k>=n-counter_r-1)
printf("1\n");
else
printf("0\n");
}
return 0;
}