HDU 4263 Red/Blue Spanning Tree(最小生成树)

HDU 4263 Red/Blue Spanning Tree(最小生成树)

http://acm.hdu.edu.cn/showproblem.php?pid=4263

题意:

       有一个N个顶点和M条边的无向图,每条边不是红色就是蓝色的,现在问你是否存在该图的一个生成树,该树正好包含了K条蓝色的边以及n-1-K条红色的边?

分析:

       首先我们只用蓝边来构成生成树,假设最多可以添加c1条边,那么c1就是蓝边构成生成树的上限.

       然后再用红边来构成生成树,假设最多可以添加c2条边,那么剩余n-1-c2条边必须要由蓝边构成.所以n-1-c2就是蓝边构成生成树的下限.

       结论:只要 n-1-c2 <=k <= c1 ,那么就必定存在由k条蓝边构成的生成树.(该结论我不知道怎么证明,网上看了很多,但是证明都不严谨.)

       我自己画了个图验证了以下,发现了矛盾.如果我没错的话,那么这道题本身就是错的:

HDU 4263 Red/Blue Spanning Tree(最小生成树)_第1张图片

对于测试数据:

4 3 2

B 1 2

B 1 4

R 2 4

输出为1. 这应该是错的吧?

AC代码:

#include
#include
using namespace std;
const int maxn=1000+10;
int fa_1[maxn],fa_2[maxn];
int findset(int x,int *fa){ return fa[x]==-1?x:fa[x]=findset(fa[x],fa); }
int bind(int i,int j,int *f)
{
    int fa=findset(i,f);
    int fb=findset(j,f);
    if(fa!=fb)
    {
        f[fa]=fb;
        return 1;
    }
    return 0;
}
int main()
{
    int n,m,k;
    while(scanf("%d%d%d",&n,&m,&k)==3&&n)
    {
        memset(fa_1,-1,sizeof(fa_1));
        memset(fa_2,-1,sizeof(fa_2));
        int c1=0,c2=0;
        while(m--)
        {
            char s[10];
            int u,v;
            scanf("%s%d%d",s,&u,&v);
            if(s[0]=='B') c1 += bind(u,v,fa_1);
            else if(s[0]='R') c2+=bind(u,v,fa_2);
        }
        if(n-1-c2<=k&&k<=c1) printf("1\n");
        else printf("0\n");
    }
    return 0;
}


你可能感兴趣的:(注意!,need,to,review,ACM--题解汇总,★★,have,a,question)