匈牙利(大视野1191,1854)

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

主持人问题准备了若干道题目,只有当选手正确回答一道题后,才能进入下一题,否则就被淘汰。为了增加节目的趣味性并适当降低难度,主持人总提供给选手几个“锦囊妙计” 这里,我们把规则稍微改变一下。假设主持人总共有m道题,选手有n种不同的“锦囊妙计”。主持人规定,每道题都可以从两种“锦囊妙计”中选择一种,而每种“锦囊妙计”只能用一次。我们又假设一道题使用了它允许的锦囊妙计后,就一定能正确回答,顺利进入下一题。现在我来到了节目现场,可是我实在是太笨了,每道题只好借助使用“锦囊妙计”来通过。如果我事先就知道了每道题能够使用哪两种“锦囊妙计”,那么你能告诉我怎样选择才能通过最多的题数吗?
Input
输入文件的一行是两个正整数n和m(0 < n <1001,0 < m < 1001)表示总共有n中“锦囊妙计”,编号为0~n-1,总共有m个问题。
以下的m行,每行两个数,分别表示第m个问题可以使用的“锦囊妙计”的编号。
注意,每种编号的“锦囊妙计”只能使用一次,同一个问题的两个“锦囊妙计”可能一样。
Output
第一行为最多能通过的题数p
Sample Input
5 6
3 2
2 0
0 3
0 4
3 2
3 2
Sample Output
4

可以理解为一个二分图;求从1开始不间断的最大匹配
可以用匈牙利来解决
如果ab边可以连或原来连着b的人可以连别的边就将ab连上
直到连不上为止。

var a:array[0..1000,0..1000] of longint;
    i,j,k,l,m,n,q,w:longint;
    b,c:array[0..1000] of boolean;
    d:array[0..1100] of longint;
function cz(p:longint):boolean;
var i,j:longint;
begin
    for i:=0 to n-1 do 
        if (a[p,i]<>0)and(b[i]=false)then begin
              b[i]:=true;
                  if(d[i]=0)or(cz(d[i]))then begin
                      d[i]:=p;exit(true);
                  end;
              end;
     exit(false);
end;
begin
    readln(n,m);
    for i:=1 to m do begin
        readln(k,l);
        a[i,k]:=1;a[i,l]:=1;
    end;
    for i:=1 to m do begin
        fillchar(b,sizeof(b),false);
        if cz(i)=true then inc(q)else break;
    end;
    writeln(q);
end.

1854

lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示。当他使用某种装备时,他只能使用该装备的某一个属性。并且每种装备最多只能使用一次。 游戏进行到最后,lxhgww遇到了终极boss,这个终极boss很奇怪,攻击他的装备所使用的属性值必须从1开始连续递增地攻击,才能对boss产生伤害。也就是说一开始的时候,lxhgww只能使用某个属性值为1的装备攻击boss,然后只能使用某个属性值为2的装备攻击boss,然后只能使用某个属性值为3的装备攻击boss……以此类推。 现在lxhgww想知道他最多能连续攻击boss多少次?
输入的第一行是一个整数N,表示lxhgww拥有N种装备 接下来N行,是对这N种装备的描述,每行2个数字,表示第i种装备的2个属性值
输出一行,包括1个数字,表示lxhgww最多能连续攻击的次数。
样例输入
3
1 2
3 2
4 5
样例输出
2
【数据范围】
对于30%的数据,保证N < =1000
对于100%的数据,保证N < =1000000

将属性视为题目,将装备视为锦囊
因为fillchar 太慢 记录每个点是否用过的数组只对当前i起作用
所以可以使用时间戳代替
上代码

var a1,a2,a3,b,c,ne,d:array[1..2000000] of longint;
    i,j,k,l,m,n,q,w,t:longint;
procedure ad(p,o:longint);
begin
    t:=t+1;a1[t]:=p;a2[t]:=o;ne[t]:=c[p];c[p]:=t;
end;
function cz(p:longint):boolean;
var i:longint;
begin
i:=c[p];
    while i<>0 do begin
        if(***b[a2[i]]<>j***)then begin b[a2[i]]:=j;
                  if(d[a2[i]]=0)or(cz(d[a2[i]]))then begin
                      d[a2[i]]:=p; exit(true);
                  end;
              end;
              i:=ne[i];
        end;
        exit(false);
end;
begin
    readln(n);
    for i:=1 to n do begin
        readln(k,l);
        ad(k,i); ad(l,i);
        if m<k then m:=k;
        if m<l then m:=l;
    end;
    for *j*:=1 to m do begin
        if cz(j) then q:=q+1 else break;
    end;
    writeln(q);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值