【BZOJ1854】游戏[SCOI2009](神奇贪心+并查集)
这道题和今年GDKOI的Day2T2很像(然而gdkoi的题用网络流可以A,这道题只能拿30)。
网址:http://www.lydsy.com/JudgeOnline/problem.php?id=1854
题目:
很显然,我们可以立即想到一种解法:如果第i个武器的属性是(a,b),那么就连i->a,i->b两条边,然后就跑网络流。为了确保要从1开始连续攻击,就可以二分答案,用网络流来判断,因为如果能从1打到n,就肯定能从1打到n-1(废话)。判断就是每次只让1~mid的属性值流过去,看一下最后的最大流是否为mid,就知道能不能从1打到mid。
代码:
var f,d,q,x,y:array[..]of longint;
a,b,ne:array[..]of longint;
n,k,nn,i,j,h,t,p,l,r,m,ans:longint;
procedure add(x,y,z:longint);
begin
a[p]:=y; b[p]:=z; ne[p]:=f[x]; f[x]:=p; inc(p);
a[p]:=x; b[p]:=; ne[p]:=f[y]; f[y]:=p; inc(p);
end;
function dfs(now,ll:longint):longint;
var i,p:longint;
begin
if now=nn then exit(ll); i:=f[now];
while i>= do begin
if(b[i]>)and(d[a[i]]=d[now]+)then begin
if ll<b[i] then p:=dfs(a[i],ll)
else p:=dfs(a[i],b[i]);
b[i]:=b[i]-p; b[i xor ]:=b[i xor ]+p;
if p> then exit(p);
end;
i:=ne[i];
end;
exit();
end;
begin
read(n);
for i:= to n do read(x[i],y[i]);
l:=; r:=; nn:=n+;
while l+<r do begin
p:=; m:=(l+r)>>;
for i:= to nn do f[i]:=-;
for i:= to n do begin
add(i,n+x[i],); add(i,n+y[i],);
end;
for i:= to n do add(,i,);
for i:= to m do add(n+i,nn,);
ans:=;
while true do begin
for i:= to nn do d[i]:=;
h:=; t:=; q[]:=; d[]:=;
repeat
i:=f[q[h]];
while i>= do begin
if(b[i]>)and(d[a[i]]=)then begin
inc(t); q[t]:=a[i]; d[a[i]]:=d[q[h]]+;
end;
i:=ne[i];
end;
inc(h);
until h>t;
if d[nn]= then break;
repeat
p:=dfs(,<<);
ans:=ans+p;
until p=;
end;
if m=ans then l:=m else r:=m;
end;
writeln(l);
end.
然而……这只是30%的解法。
100%的解法。。。应该怎么说呢。。。并查集+神奇贪心?
参考黄学长的博客:http://hzwer.com/2950.html
其实就是把属性为(a,b)的武器看成一条边,然后就生成了一个有10000个结点的无向图,于是我们就要把点和边进行配对(就像上面的二分图匹配一样)。对于其中每一个联通块,有两种情况:
1、假设它有k个节点,如果有k-1条边,那么肯定有一个节点匹配不到(把它看成一棵有根树,每个节点匹配他的父亲)。为了确保答案最优,那么我们就把这个不能被匹配到的节点定为这个联通块中属性值最大的节点。
2、如果这个联通块中有>=k条边,这个联通块中就存在环,一定能把全部的点都找到匹配的边(看成环套树,环上的节点一定能被匹配到,而环上的树就按照第一种情况匹配)
于是就可以用并查集,每次往图中增加一条边时,如果这两个点在同一个联通块,那么这个联通块的根就可以被匹配(这个联通块在加边之后一定成为第二种情况),否则判断是否两个联通块是否有一个存在环(一个有环图无论怎么加还是有环)(我一开始就被这个坑了),否则把编号较小的点修改为可以被匹配,然后把它接到编号较大的点上。这样处理,就可以使每个联通块中最多有一个节点不能被选择,而这个不能被选择的点一定是该联通块中编号最大的节点。最后扫一遍就好了。
代码:
#include<iostream>
#include<cstdio>
using namespace std;
int f[],v[]={};
int find(int x)
{
if(f[x]=x)return x;
int ret=find(f[x]); f[x]=ret;
return ret;
}
int main()
{
int n,i,x,y;
scanf("%d",&n);
for(i=;i<=n+;i++) f[i]=i;
for(i=;i<=n;i++){
scanf("%d%d",&x,&y);
int fx=find(x),fy=find(y);
if(fx==fy)v[fx]=;
else {
if(fx>fy){
int t=fx; fx=fy; fy=t;
}
if(v[fx])v[fy]=;else v[fx]=;
f[fx]=fy;
}
}
int ans=;
while(v[ans]&&ans<=n)ans++;
printf("%d",ans-);
}
P.S. 当我做这道题时,ZN大神犇看了一眼后,说:“这不是傻逼贪心吗?” orz orz orz ZN大神犇
【BZOJ1854】游戏[SCOI2009](神奇贪心+并查集)的更多相关文章
- BZOJ-1854 游戏 二分图匹配 (并查集)
1854: [Scoi2010]游戏 Time Limit: 5 Sec Memory Limit: 162 MB Submit: 3372 Solved: 1244 [Submit][Status] ...
- bzoj1854 游戏题解(二分图/并查集)
1854: [Scoi2010]游戏 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 5547 Solved: 2229[Submit][Status] ...
- [BZOJ1854][Scoi2010]游戏(二分图匹配/并查集)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1854 分析:很裸的一道二分图匹配对吧,但是在hzwer的blog上看见神奇的并查集做法 ...
- POJ 1456 Supermarket(贪心+并查集)
题目链接:http://poj.org/problem?id=1456 题目大意:有n件商品,每件商品都有它的价值和截止售卖日期(超过这个日期就不能再卖了).卖一件商品消耗一个单位时间,售卖顺序是可以 ...
- poj1456(贪心+并查集)
题目链接: http://poj.org/problem?id=1456 题意: 有n个商品, 已知每个商品的价格和销售截止日期, 每销售一件商品需要花费一天, 即一天只能销售一件商品, 问最多能买多 ...
- Codeforces 437D The Child and Zoo(贪心+并查集)
题目链接:Codeforces 437D The Child and Zoo 题目大意:小孩子去參观动物园,动物园分非常多个区,每一个区有若干种动物,拥有的动物种数作为该区的权值.然后有m条路,每条路 ...
- POJ - 1456 贪心+并查集
做法一:直接贪心,按照利润排序,然后直接尽量给每个活动安排到最晚的时间即可.时间复杂度O(n * d)当d都为10000时,很容易超时.由于这题数据比较水,所有贪心未超时. AC代码 #include ...
- poj1456 Supermarket 贪心+并查集
题目链接:http://poj.org/problem?id=1456 题意:有n个物品(0 <= n <= 10000) ,每个物品有一个价格pi和一个保质期di (1 <= pi ...
- GYM 101173 F.Free Figurines(贪心||并查集)
原题链接 题意:俄罗斯套娃,给出一个初始状态和终止状态,问至少需要多少步操作才能实现状态转化 贪心做法如果完全拆掉再重装,答案是p[i]和q[i]中不为0的值的个数.现在要求寻找最小步数,显然要减去一 ...
随机推荐
- Ubuntu下MongoDB的安装和使用
本博文介绍了MongoDB,并详细指引读者在Ubuntu下MongoDB的安装和使用.本教程在Ubuntu14.04下测试通过.(2017.09.07) 安装MongoDB MongoDB安装很简单, ...
- ios 制作自已的framework
本文转载至 http://blog.csdn.net/chen505358119/article/details/9190731 ios中我们写的代码有时不愿意让别人看到,可能对它进行封装,生成一 ...
- ASP.NET中RegisterStartupScript和RegisterClientScriptBlock有区别吗
今天用RegisterClientScriptBlock()方法调用了alertify.js(绚丽的实现alert()同样的提示功能): Page.ClientScript.RegisterClien ...
- Highway
Highway Accepted : 78 Submit : 275 Time Limit : 4000 MS Memory Limit : 65536 KB Highway In ICPCC ...
- <2013 12 28> AOI PCB设计
主要设计指标: “3.多块拼板最大尺寸:60*50(CM)4. 检测速度:(230-250)片/小时 5.检测通过率:98%6.最窄线宽:设两种精度 A.最窄线宽:0.2mm, 识别精度 0.1mm ...
- JavaSctipt语句for循环的思考
一.语法 for (语句 1; 语句 2; 语句 3) { 被执行的代码块; } 语句 1: 在循环(代码块)开始前执行, 可选. 语句 2: 定义运行循环(代码块)的条件, 可选, 如果省略了语句 ...
- 类加载器(ClassLoader)
1. 类加载器概述 1.1 类加载器的作用 把 .class 文件加载到 JVM 的方法区中,变成一个 Class 对象! 1.2 类加载器分类 类加载器也是一个类: ClassLoader; Jav ...
- 约束、自定义异常、hashlib模块、logging日志模块
一.约束(重要***) 1.首先我们来说一下java和c#中的一些知识,学过java的人应该知道,java中除了有类和对象之外,还有接口类型,java规定,接口中不允许在方法内部写代码,只能约束继承它 ...
- matlab学习笔记之基础知识(一)
一.两种特殊数据类型 1.元胞数组 元胞数组是MATLAB的一种特殊数据类型,可以将元胞数组看做一种无所不包的通用矩阵,或者叫做广义矩阵.组成元胞数组的元素可以是任何一种数据类型的常数或者常量,每 ...
- 通过Python操作hbase api
# coding=utf-8 # Author: ruin """ discrible: """ from thrift.transport ...