游戏

1 篇文章 0 订阅

Description

馒头卡得了忧郁综合症,包子卡正在想办法开导她。
机智的白子卡决定陪着馒头卡玩游戏,他从魔法世界里变出一张无向连通图,每条边上都有边权。包子卡定义一条路径的权值为经过边中的最大权值,馒头卡则定义两点的 最短路径为所有路径中权值最小的路径权。
每次馒头卡先选出两个点  m1,m2   m 1 , m 2 ,然后包子卡会拿出两堆灵魂宝石,一堆有  m    m   个,另一堆有  b    b   个。然后馒头卡先从一堆中选出若干个灵魂宝石拿走,接下来包子卡重复同样的操作,如此反复,直到取走最后一颗灵魂宝石,然后取走最后一颗宝石的人获胜。
包子卡认为这样游戏太简单,于是他会不定期向这张图上加上一些边,以增大游戏难度。
馒头卡具有预知未来的能力,她看到了自己和包子卡在未来游戏中的选择,以及包子卡增加的边。现在对于每次游戏,馒头卡想知道自己是否存在必胜的方法,但是预知未来已经消耗了她太多精力,出于疲惫她只好找到了你。

Input

第一行两个数  N    N    M    M   ,表示这张无向图初始的点数和边数。
接下来  M    M   行,每行三个数  u,v,q    u , v , q   表示点  u    u   和点  v    v   之间存在一条权值为  q    q   的边。
接下来一行一个数  Q   Q ,表示操作总数。
接下来  Q    Q   行,表示操作,每行格式为下面两条中的一条:
1 add u v q 1   a d d   u   v   q : 表示在  u    u    v    v   之间加上一条边权为  q    q   的边。
2 game m1 m2 b1 b2 2   g a m e   m 1   m 2   b 1   b 2 :表示一次游戏,其中馒头卡的选择点 m1,m2 m 1 , m 2 ,包子卡的选择点 b1,b2 b 1 , b 2

Output

对于每个 game g a m e 输出一行,若馒头卡存在必胜策略,则输出 madoka ‘ m a d o k a ′ ,否则输出 Baozika ‘ B a o z i k a ′ ,以回车结尾。

Sample Input

5 6
1 2 3
2 3 6
4 2 4
5 3 5
3 4 5
5 1 5
4
game 1 3 4 3
game 1 5 2 4
add 2 5 4
game 1 5 3 4

Sample Output

Baozika
madoka
madoka

Data Constraint

N5000;M100000;Q150000; N ≤ 5000 ; M ≤ 100000 ; Q ≤ 150000 ;
边权 q1015 q ≤ 10 15 ; add a d d 操作数 1000 ≤ 1000
数据保证 1u,v,m1,m2,b1,b2n, 1q, 1 ≤ u , v , m 1 , m 2 , b 1 , b 2 ≤ n ,   1 ≤ q ,
m1m2  b1b2 m 1 ≠ m 2   且   b 1 ≠ b 2

Solution

就是求两点间最小的瓶颈路,瓶颈路就是一条路径上最大的那条边。
先考虑什么时候包子卡赢,什么时候馒头卡赢。如果存在两个数 S1=S2 S 1 = S 2 ,假设一个人在 S1 S 1 中取了  a    a   ,那只要相应的在另一堆  S2    S 2   中取  a    a   个就可以了,这样最后保证后手必赢。相应的如果一开始 S1S2 S 1 ≠ S 2 ,则先手赢。
那两点的最小瓶颈路是什么呢,其实就是对应着整幅图的最小生成树,用LCA倍增上去就可以得到瓶颈路了。
可以发现, add a d d 操作数很小,所以每次可以从两点 LCA L C A 倍增上去找到瓶颈路,也就是最大值,把那条路打个 tag t a g 封住,连接新边,从 LCA L C A 上往下全部更新一遍即可。

Code

const   maxn=7005;
        maxm=150000;
        w=13;
var n,m,i,tot,q:longint;
        c:char;
    g,fa,deep:array[0..maxn] of longint;
    a:array[0..maxm,1..2] of longint;
    len:array[0..maxm] of int64;
    f,e:array[0..maxn,0..w] of longint;
    ll:array[0..maxn,0..w] of int64;
    next,yy:array[1..maxn*2] of longint;
    cost:array[1..maxn*2] of int64;
    p:array[0..maxm] of boolean;
function make(x,y:longint;z:int64):longint;
begin
    inc(tot);
    yy[tot]:=y;
    cost[tot]:=z;
    next[tot]:=g[x];
    g[x]:=tot;
end;
procedure swap(var x,y:longint);
var t:longint;
begin
    t:=x;
    x:=y;
    y:=t;
end;
function dis(x,y:longint):int64;
var v,i,l:longint;
    len:int64;
begin
    if deep[x]<deep[y] then swap(x,y);
    l:=deep[x]-deep[y];v:=0;
    len:=-high(int64);
    while l<>0 do begin
        if l mod 2=1 then begin
            if len<ll[x,v] then len:=ll[x,v];
            x:=f[x,v];
        end;
        l:=l div 2;
                inc(v);
    end;
    if x=y then exit(len);
        for i:=w downto 0 do begin
            while f[x,i]<>f[y,i] do begin
                if len<ll[x,i] then len:=ll[x,i];
                x:=f[x,i];
                if len<ll[y,i] then len:=ll[y,i];
                y:=f[y,i];
            end;
        end;
        if len<ll[x,0] then len:=ll[x,0];
        if len<ll[y,0] then len:=ll[y,0];
    exit(len);
end;
procedure query(x1,y1,x2,y2:longint);
var a1,a2:int64;
begin
    a1:=dis(x1,y1);
    a2:=dis(x2,y2);
    if a1=a2 then writeln('Baozika') else
    writeln('madoka');
end;
procedure qsort(x,y:longint);
var     i,j:longint;
        k:int64;
begin
    i:=x;
    j:=y;
    k:=len[(x+y) div 2];
    repeat
        while len[i]<k do inc(i);
        while len[j]>k do dec(j);
        if i<=j then begin
            a[0]:=a[i];
            a[i]:=a[j];
            a[j]:=a[0];
            len[0]:=len[i];
            len[i]:=len[j];
            len[j]:=len[0];
                        inc(i);dec(j);
        end;
    until i>j;
    if i<y then qsort(i,y);
    if j>x then qsort(x,j);
end;
procedure init;
var     i:longint;
begin
    readln(n,m);
    for i:=1 to m do
    readln(a[i,1],a[i,2],len[i]);
end;
function get(x:longint):longint;
begin
    if fa[x]=x then exit(x);
    fa[x]:=get(fa[x]);
    exit(fa[x]);
end;
procedure build;
var i,fax,fay:longint;
begin
    for i:=1 to n do fa[i]:=i;
    for i:=1 to m do begin
        fax:=get(a[i,1]);
        fay:=get(a[i,2]);
        if fax<>fay then begin
            fa[fax]:=fay;
            make(a[i,1],a[i,2],len[i]);
            make(a[i,2],a[i,1],len[i]);
        end;
    end;
end;
procedure dfs(x:longint);
var i,y:longint;
begin
    for i:=1 to w do begin
        f[x,i]:=0;
        ll[x,i]:=0;
        e[x,i]:=0;
    end;
    for i:=1 to w do if f[x,i-1]=0 then break else begin
        if ll[x,i-1]>=ll[f[x,i-1],i-1] then begin
            ll[x,i]:=ll[x,i-1];
            e[x,i]:=e[x,i-1];
        end else begin
            ll[x,i]:=ll[f[x,i-1],i-1];
            e[x,i]:=e[f[x,i-1],i-1];
        end;
        f[x,i]:=f[f[x,i-1],i-1];
    end;
    i:=g[x];
    while i<>0 do begin
        y:=yy[i];
        if (p[i]) and (f[x,0]<>y) then begin
            deep[y]:=deep[x]+1;
            f[y,0]:=x;
            ll[y,0]:=cost[i];
            e[y,0]:=i;
            dfs(y);
        end;
        i:=next[i];
    end;
end;
procedure change(x0,y0:longint;z:int64);
var i,l,v,x,y,ei:longint;
    len:int64;
begin
    x:=x0;y:=y0;
    if deep[x]<deep[y] then swap(x,y);
    l:=deep[x]-deep[y];v:=0;len:=-high(int64);
    while l<>0 do begin
        if l mod 2=1 then begin
            if len<ll[x,v] then begin
                len:=ll[x,v];
                ei:=e[x,v];
            end;
            x:=f[x,v];
        end;
        l:=l div 2;
        inc(v);
    end;
    if x<>y then begin
        for i:=w downto 0 do begin
            while f[x,i]<>f[y,i] do begin
                if len<ll[x,i] then begin
                    len:=ll[x,i];
                    ei:=e[x,i];
                end;
                x:=f[x,i];
                if len<ll[y,i] then begin
                    len:=ll[y,i];
                    ei:=e[y,i];
                end;
                y:=f[y,i];
            end;
        end;
        if len<ll[x,0] then begin
            len:=ll[x,0];
            ei:=e[x,i];
        end;
        if len<ll[y,0] then begin
            len:=ll[y,0];
            ei:=e[y,i];
        end;
        x:=f[x,0];
    end;
    if z>len then exit;
    make(x0,y0,z);
    make(y0,x0,z);
    p[ei]:=false;
    p[ei xor 1]:=false;
    dfs(x);
end;
procedure main;
var j,i,x,y,x1,y1,x2,y2:longint;
        z:int64; 
begin
    tot:=1;
    fillchar(p,sizeof(p),true);
    qsort(1,m);
    build;
    dfs(1);
        readln(q);
    for i:=1 to q do begin
                read(c);
        if c='g' then begin
                        while c<>' ' do read(c);
            readln(x1,y1,x2,y2);
            query(x1,y1,x2,y2);
        end else begin
                        while c<>' ' do read(c);
            readln(x,y,z);
            change(x,y,z);
        end;
    end;
end;
begin
    init;
    main;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值