zoukankan      html  css  js  c++  java
  • 魏迟燕的自走棋 题解(并查集+思维)

    题目链接

    题目大意

    \(n(n \leq 1e5)\)个人,\(m(m\leq 1e5)\)件装备

    每件装备可以给1个或2个人,而且每件装备有一个战力值,获得这个装备的人可以获得此战力值

    要求每个人只能装备一件装备,每件装备只能分配给一个人。

    求总战力值最大

    思路

    官方题解:

    首先我们考虑把 m件装备看作 m 条连接两个点的边(如果 k=1 则当成自环)。于是我们的问题转化为选出一张边权和最大的生成子图。

    考虑什么样的生成子图是合法的。我们要求选中的边能够和点一一配对,显然每个联通块的边数不能超过点数。同时又因为每个联通块都至少有点数-1条边,因此每个联通快要么是树,要么是基环树。

    一个结论是每次都选最大边一定不劣。

    一旦我们选择一条最大边后,我们把两个点缩成一个点(选中非自环的情况),或者直接把这个点丢掉(选中自环的情况),就面临一个规模更小且完全一致的问题,可以继续执行选取最大边的策略。

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    const int maxn=1e5+5,inf=0x3f3f3f3f;
    //int mod=1e9+7;
    const int eps=1e-3;
    int n,m;
    int p[3];
    int fa[maxn];
    bool flag[maxn];
    struct edge{
        int u,v,w;
    }e[maxn];
    bool cmp(edge a,edge b){
        return a.w>b.w;
    }
    int findd(int x){
        return x==fa[x]?x:fa[x]=findd(fa[x]);
    }
    signed main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            fa[i]=i;
        }
        for(int i=1,num,val;i<=m;i++){
            scanf("%d",&num);
            for(int i=1;i<=num;i++){
                scanf("%d",&p[i]);
            }
            scanf("%d",&val);
            if(num==1) p[2]=p[1];
            e[i]={p[1],p[2],val};
        }
        sort(e+1,e+1+m,cmp);
        ll ans=0;
        for(int i=1;i<=m;i++){
            int x=findd(e[i].v),y=findd(e[i].u);
            if(x!=y){
                if(!flag[x]){
                    flag[x]=1;
                    fa[x]=y;
                    ans+=e[i].w;
                }else if(!flag[y]){
                    flag[x]=1;
                    fa[y]=x;
                    ans+=e[i].w;
                }
            }else{
                if(!flag[x]){
                    flag[x]=1;
                    ans+=e[i].w;
                }
            }
        }
        printf("%lld\n",ans);
        return 0;
    }
    
    
    不摆烂了,写题
  • 相关阅读:
    mybatis-3.x的错误
    iBatis2错误:com.ibatis.common.jdbc.exception.NestedSQLException:
    jdbc零散知识点
    valueOf与new的区别
    插入一条记录并获取自增的id
    存储过程的简单使用
    事务的隔离级别
    date类型的转换
    批量处理异常
    非确定的自动机NFA确定化为DFA
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/14424130.html
Copyright © 2011-2022 走看看