• BZOJ4883 [Lydsy2017年5月月赛]棋盘上的守卫


    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:BZOJ4883

    正解:贪心

    解题报告:

      又是用贪心模拟费用流…

      考虑直接跑费用流,复杂度很不靠谱,那么用之前$get$的姿势:用贪心模拟费用流。

      费用流建图的话非常$simple$,如果我们用类似最小生成树的方式,把边按边权从小到大往里面加。

      我们观察一下费用流建的那张图,一次增广,本质上可以看成是选择了一个行编号和一个列编号,那么我们考虑每个点加入时的情况。相当于是每个行、列所代表的点的入度强制要为1,那么只有可能是带一个环的树;如果图是一棵树,那么必然可以匹配;如果是一棵n条边的基环树,那么也能匹配。分类讨论,除非两个都为图,否则就能匹配。按最小生成树的方式做就好了。

    //It is made by ljh2000
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <queue>
    #include <cmath>
    #include <ctime>
    #define lc root<<1
    #define rc root<<1|1
    #define reg(i,x) for(int i=first[x];i;i=nxt[i])
    using namespace std;
    typedef long long LL;
    const int MAXN = 200011;
    int n,m,cnt,fa[MAXN];
    bool G[MAXN];
    LL ans;
    struct edge{ int x,y,z; }e[MAXN];
    inline bool cmp(edge q,edge qq){ return q.z<qq.z; }
    inline int find(int x){ if(fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; }
    inline void link(int x,int y,int z){ e[++cnt].x=x; e[cnt].y=y; e[cnt].z=z; }
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void work(){
    	n=getint(); m=getint(); int x,y,z;
    	for(int i=n+m;i>=1;i--) fa[i]=i;
    	for(int i=1;i<=n;i++) 
    		for(int j=1;j<=m;j++) {
    			z=getint();
    			link(i,j+n,z);
    		}
    	sort(e+1,e+cnt+1,cmp);
    	for(int i=1;i<=cnt;i++) {
    		x=find(e[i].x); y=find(e[i].y);
    		if(G[x] && G[y]) continue;
    		if(x!=y){
    			fa[x]=y;
    			G[y]|=G[x];
    		}
    		else G[y]=1;
    		ans+=e[i].z;		 
    	}		
    	printf("%lld",ans);
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("4883.in","r",stdin);
    	freopen("4883.out","w",stdout);
    #endif
        work();
        return 0;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

  • 相关阅读:
    函数二
    python控制台输出带颜色的文字方法
    is 和 == 的区别
    基本数据类型(dict)
    基本数据类型(list,tuple)
    基本数据类型(int,bool,str)
    Python运算符与编码
    Java并发编程:synchronized
    泛型中? super T和? extends T的区别
    java中的匿名内部类总结
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6861827.html
Copyright © 2020-2023  润新知