zoukankan      html  css  js  c++  java
  • ●BZOJ 1854 [Scoi2010]游戏

    题链:

    http://www.lydsy.com/JudgeOnline/problem.php?id=1854

    题解:

    并查集(还可以用匈牙利算法进行单路增广的二分图匹配)

    把每个武器看成是一条边,每个伤害值看成是一个点,
    那么每一条边就连接了两个点。
    并把一条边e与其一个端点u的“对应”表示为用这个武器e打出伤害u。
    对于一个联通块,我们考虑把点和边一一对应,使得被对应的点尽量多。
    1).对于一棵树来说,就会有一个点没有边与之对应,令那个点为联通块里编号最大的点。
    2).而对于非树图来说,即存在环,那么所有点都可以与一条边对应。
    这样的话,就可以用并查集维护联通信息了。做法如下:
    对于输入的 x,y,我们找到其各自所在联通块里编号最大的点(也是根)fx,fy。
    如果 fx==fy,那么表明加入这条边后这个联通块出现了环,则 vis[fx]=1;
    否则(令 fx<fy),表明是两个联通块合并了,则让编号较小的那个(即fx)可以有边与它对应,vis[fx]=1;
    最后从左往右遍历一遍 vis,找到第一个 i,使得 vis[i]=0,那么答案即为 i-1。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define MAXN 1050000
    #define filein(x) freopen(#x".in","r",stdin);
    #define fileout(x) freopen(#x".out","w",stdout);
    using namespace std;
    bool vis[MAXN];
    int fa[MAXN];
    int N;
    int find(int x){
    	return x==fa[x]?x:fa[x]=find(fa[x]);
    }
    void merge(int x,int y){
    	if(x>y) swap(x,y);
    	fa[x]=y; vis[x]=1;
    }
    int main()
    {
    	filein(game); fileout(game);
    	scanf("%d",&N);
    	for(int i=0;i<=1000000;i++) fa[i]=i;
    	for(int i=1,x,y,fx,fy;i<=N;i++){
    		scanf("%d%d",&x,&y);
    		fx=find(x); fy=find(y);
    		if(fx==fy) vis[fx]=1;
    		else merge(fx,fy);
    	}
    	for(int i=1;i<=1000000;i++) if(!vis[i]){
    		printf("%d",i-1); break;
    	}
    	return 0;
    }
    

  • 相关阅读:
    Uipath-Close Application和Close Window区别
    我与某猪同学斗智斗勇的那些事
    可视报表(Project)
    自定义函数(Power Query 之 M 语言)
    报表(Project)
    拆分…Split…(Power Query 之 M 语言)
    参加Mos考试
    主要视图展示(Project)
    听听文档(视频)-Power Pivot
    突出显示(Project)
  • 原文地址:https://www.cnblogs.com/zj75211/p/8005115.html
Copyright © 2011-2022 走看看