zoukankan      html  css  js  c++  java
  • HDU 2860 (并查集)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2860

    题目大意:新兵入伍。三种操作:①入伍②合并队伍③查找一个队伍里面战斗力最弱的。注意队伍编号从0开始。

    解题思路

    单看入伍的话,很容易想到以士兵为单位建立并查集。

    然而到了合并队伍、查询的时候,就没办法了。

    更直接的,以队伍为单位建立并查集,这样只要$f[x]!=x$,说明队伍已被合并。

    当然,最重要的,就是查询之前,没必要路径压缩,因为只需要简单判断$f[x]!=x$,而不是查f[x]的具体值。

    同时用cap数组维护每个队伍的最弱战斗力。

    维护

    ①入伍时候,先Judge $f[x]!=x$。

    若存在,此时只需Min更新一下队伍的战斗力就可以。

    ②合并队伍,先Judge $f[x]==x$&&$f[y]==y$&&$x!=y$,直接令$f[y]=x$,并且更新,不需要路径压缩。

    反之,拒绝合并。

    查询

    ①成功输出的条件是:$f[x]==x$&&$cap[x]!=inf$

    ②空队伍的条件是:$f[x]==x$&&$cap[x]==inf$ (注意,转移之后,就算是空队伍,也在③中处理)

    ③转移队伍的条件是:$f[x]!=x$ ,查询时候,再find路径压缩即可。

    代码

    #include "cstdio"
    #include "cstring"
    #include "algorithm"
    using namespace std;
    #define maxn 100005
    #define inf 0x3f3f3f3f
    int f[maxn],cap[maxn];
    int find(int x) {return x!=f[x]?f[x]=find(f[x]):x;}
    int main()
    {
        //freopen("in.txt","r",stdin);
        int n,k,m,R,C;
        while(scanf("%d%d%d",&n,&k,&m)!=EOF)
        {
            for(int i=0;i<=n;i++) f[i]=i;
            memset(cap,inf,sizeof(cap));
            for(int i=1;i<=k;i++)
            {
                scanf("%d%d",&R,&C);
                cap[C]=min(cap[C],R);
            }
            char cmd[5];
            for(int i=1;i<=m;i++)
            {
                scanf("%s",&cmd);
                if(cmd[0]=='A')
                {
                    scanf("%d%d",&R,&C);
                    if(f[C]!=C) {printf("Reject
    ");continue;}
                    cap[C]=min(cap[C],R);
                    printf("Accept
    ");
                }
                if(cmd[0]=='M')
                {
                    scanf("%d%d",&R,&C);
                    if(f[R]==R&&f[C]==C&&R!=C) {f[C]=R;cap[R]=min(cap[R],cap[C]);printf("Accept
    ");}
                    else printf("Reject
    ");
                }
                if(cmd[0]=='G')
                {
                    scanf("%d",&R);
                    if(f[R]==R&&cap[R]!=inf) printf("Lowest rate: %d.
    ",cap[R]);
                    else if(f[R]==R&&cap[R]==inf) printf("Company %d is empty.
    ",R);
                    else if(f[R]!=R) printf("Company %d is a part of company %d.
    ",R,find(R));
                }
            }
            printf("
    ");
        }
    }
  • 相关阅读:
    IOS设计模式之四(备忘录模式,命令模式)
    IOS设计模式之三(适配器模式,观察者模式)
    IOS设计模式之二(门面模式,装饰器模式)
    IOS设计模式之一(MVC模式,单例模式)
    C#调用C++导出(dllexport)方法
    C# 多任务之 Task
    C# Remoting的一个简单例子
    C#中指针使用总结
    C# fixed详解
    C#中virtual和abstract的区别
  • 原文地址:https://www.cnblogs.com/neopenx/p/4572566.html
Copyright © 2011-2022 走看看