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
N≤5000;M≤100000;Q≤150000;
N
≤
5000
;
M
≤
100000
;
Q
≤
150000
;
边权
q≤1015
q
≤
10
15
;
add
a
d
d
操作数
≤1000
≤
1000
数据保证
1≤u,v,m1,m2,b1,b2≤n, 1≤q,
1
≤
u
,
v
,
m
1
,
m
2
,
b
1
,
b
2
≤
n
,
1
≤
q
,
m1≠m2 且 b1≠b2
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
个就可以了,这样最后保证后手必赢。相应的如果一开始
S1≠S2
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.