HDU Red/Blue Spanning Tree【生成树】

题意: 给出一个有N 个节点,和M 条边,这些边分为 蓝色和红色的,问是否存在一种情况为 恰好用 k个蓝色的边,和已有的若干条红色边,将原图连成一棵树。

分析: 两次 Kruskal ,第一次的时候先把能用的红色边全部用上,然后用蓝色边,这些用到的蓝色边都是最终的生成树所必需的,将其标记

         如果发现需要的蓝色边数目大于 K,或用完了能用的蓝色边之后图还未连通,则不存在符合条件的情况

          第二次Kruskal的时候,先把之前标记的蓝色边全部用上,然后在剩下的蓝色边选出能用的边,如果总数能达到K则存在符合的情况。

 

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct Edge
{
    int from,to,co;
}b[3000000],r[3000000];
int bn,rn;
int f[1005];
int v[3000005];
int find(int x)
{
    return f[x]==x?x:(f[x]=find(f[x]));
}
void join(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy)
    {
        if(fx<fy)
            f[fy]=fx;
        else f[fx]=fy;
    }
}
int n,tt,k;
int kruskal_1()
{
    int i,x,y;
    for(i=1;i<=n;i++)
        f[i]=i;
    tt=0;
    for(i=0;i<rn;i++)
    {
        x=find(r[i].from);
        y=find(r[i].to);
        if(x!=y)
            join(x,y);
    }
    for(i=0;i<bn;i++)
    {
        x=find(b[i].from);
        y=find(b[i].to);
        if(x!=y)
        {
            tt++;
            join(x,y);
            v[i]=1;
        }
    }
    int tmp=find(1);
    for(i=1;i<=n;i++)
        if(find(i)!=tmp)
            return 0;
    if(tt>k)
        return 0;
    return 1;
}
int kruskal_2()
{
    if(tt==k)return 1;
    int i,x,y;
    for(i=1;i<=n;i++)
        f[i]=i;
    for(i=0;i<bn;i++)
        if(v[i])
            join(b[i].from,b[i].to);
    for(i=0;i<bn;i++)
    {
        if(v[i])
            continue;
        x=find(b[i].from);
        y=find(b[i].to);
        if(x!=y)
        {
            tt++;
            join(x,y);
            if(tt==k)
                return 1;
        }
    }
    return 0;
}
int main()
{
    int m,i,j,aa,bb;
    char s[2];
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        if(n==0&&m==0&&k==0)
            break;
        bn=rn=0;
        for(i=0;i<m;i++)
        {
            scanf("%s%d%d",s,&aa,&bb);
            if(s[0]=='B')
            {
                b[bn].from=aa;
                b[bn++].to=bb;
            }
            else 
            {
                r[rn].from=aa;
                r[rn++].to=bb;
            }
        }
        memset(v,0,sizeof(v));
        if(kruskal_1()==0)
        {
            printf("0\n");
            continue;
        }
        if(kruskal_2())
            printf("1\n");
        else printf("0\n");
    }
    return 0;
}

 

posted @ 2012-08-25 19:41  'wind  阅读(289)  评论(0编辑  收藏  举报