10.28T6 动态维护最小生成树

5163 -- 【11.04题目】玩游戏

Description

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

Input

  第一行两个数N和M,表示这张无向图初始的点数与边数;
  接下来M行,每行三个数u,v,q,表示点u和点v之间存在一条权值为q的边;
  接下来一行一个数Q,表示操作总数;
  接下来Q行,表示操作,每行格式为下面两条中的一条:
  1.add u v q:表示在u与v之间加上一条边权为q的边;
  2.game m1 m2 b1 b2:表示一次游戏,其中小A的选择点m1,m2,小B的选择点b1,b2。
  数据保证1≤u,v,m1,m2,b1,b2≤n,1≤q,m1≠m2 且 b1≠b2

Output

  对于每个game输出一行,若小A存在必胜策略,则输出“madoka”,否则输出“Baozika”,以回车结尾

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

Hint




 
 
 
我们先求出一个最小生成树,然后每加上一条边我们就重新dfs一遍维护
至于那个博弈实际上就是一个nim博弈,直接异或起来判断是否是0就可以了
code:
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<string>
  6 #define N 500005
  7 using namespace std;
  8 long long n,m;
  9 struct node {
 10     long long u,v,w,used;
 11 } e[N],t[N];
 12 int first[N],nxt[N],cnt;
 13 inline void add(long long u,long long v,long long w,long long d) {
 14     e[++cnt].u=u;
 15     e[cnt].v=v;
 16     e[cnt].w=w;
 17     e[cnt].used=d;
 18     nxt[cnt]=first[u];
 19     first[u]=cnt;
 20 }
 21 inline bool cmp(const node&a,const node&b) {
 22     return a.w<b.w;
 23 }
 24 long long fa[N];
 25 inline long long find(long long x) {
 26     if(x!=fa[x])return fa[x]=find(fa[x]);
 27     return fa[x];
 28 }
 29 inline void merge(long long x,long long y) {
 30     long long f1=find(x),f2=find(y);
 31     if(f1!=f2) {
 32         fa[f1]=f2;
 33     }
 34 }
 35 inline void kruskal() {
 36     long long cnt_=0;
 37     for(long long i=1; i<=m; ++i) {
 38         long long u=t[i].u,v=t[i].v,w=t[i].w;
 39         if(find(u)!=find(v)) {
 40             merge(u,v);
 41             add(u,v,w,1);
 42             add(v,u,w,1);
 43             cnt_++;
 44             if(cnt_==n-1)return;
 45         }
 46     }
 47 }
 48 struct T {
 49     long long id,max;
 50 };
 51 long long dep[N],mx[N][30],f[N][30],bianhao[N][30];
 52 T lca(long long x,long long y) {
 53     if(dep[x]<dep[y])swap(x,y);
 54     long long id,max0=0;
 55     for(long long i=15; i>=0; i--) {
 56         if(dep[f[x][i]]>=dep[y]) {
 57             if(max0<mx[x][i]) {
 58                 max0=mx[x][i];
 59                 id=bianhao[x][i];
 60             }
 61             x=f[x][i];
 62         }
 63         if(x==y)return (T) {
 64             id,max0
 65         };
 66     }
 67     for(long long i=15; i>=0; i--) {
 68         if(f[x][i]==f[y][i])continue;
 69         if(max0<mx[x][i]) {
 70             max0=mx[x][i];
 71             id=bianhao[x][i];
 72         }
 73         if(max0<mx[y][i]) {
 74             max0=mx[y][i];
 75             id=bianhao[y][i];
 76         }
 77         x=f[x][i];
 78         y=f[y][i];
 79     }
 80     T temp;
 81     if(max0<mx[y][0]) {
 82         max0=mx[y][0];
 83         id=bianhao[y][0];
 84     }
 85     if(max0<mx[x][0]) {
 86         max0=mx[x][0];
 87         id=bianhao[x][0];
 88     }
 89     temp.id=id,temp.max=max0;
 90     return temp;
 91 }
 92 long long dis[N];
 93 inline void dfs(long long x) {
 94     for(long long i=first[x]; i; i=nxt[i]) {
 95         if(!e[i].used)continue;
 96         long long v=e[i].v;
 97         if(v==f[x][0])continue;
 98         f[v][0]=x;
 99         bianhao[v][0]=i;
100         dep[v]=dep[x]+1;
101         mx[v][0]=e[i].w;
102         dfs(v);
103     }
104 }
105 inline void build() {
106     f[1][0]=1;
107     dep[1]=0;
108     dfs(1);
109     for(long long i=1; i<=15; ++i) {
110         for(long long j=1; j<=n; ++j) {
111             f[j][i]=f[f[j][i-1]][i-1];
112             mx[j][i]=max(mx[j][i-1],mx[f[j][i-1]][i-1]);
113             if(mx[j][i]==mx[j][i-1])bianhao[j][i]=bianhao[j][i-1];
114             else bianhao[j][i]=bianhao[f[j][i-1]][i-1];
115         }
116     }
117 }
118 inline long long read(){
119     long long x=0,f=1;
120     char c=getchar();
121     while(!isdigit(c)){
122         if(c=='-')f=-1;
123         c=getchar();
124     }
125     while(isdigit(c)){
126         x=(x<<3)+(x<<1)+c-'0';
127         c=getchar();
128     }
129     return x*f;
130 }
131 int main() {
132 //    freopen("game1.in","r",stdin);
133     n=read(),m=read();
134     for(long long i=1; i<=n; ++i)fa[i]=i;
135     for(long long i=1; i<=m; ++i) {
136         t[i].u=read(),t[i].v=read(),t[i].w=read();
137     }
138     sort(t+1,t+m+1,cmp);
139     kruskal();
140     build();
141     //cout<<e[lca(2,5).id].u<<" "<<e[lca(2,5).id].v<<"!!!!!";
142     long long Q;
143     Q=read();
144     while(Q--) {
145         string k;
146         cin>>k;
147         if(k=="add") {
148             long long u,v,w;
149             u=read(),v=read(),w=read();
150             T temp=lca(u,v);
151             if(temp.max>w) {
152                 e[temp.id].used=0;
153 //                cout<<u<<" "<<v<<" u->"<<e[temp.id].u<<" v->"<<e[temp.id].v<<" max->"<<temp.max<<'
';
154                 if(e[temp.id+1].u==e[temp.id].v&&e[temp.id+1].v==e[temp.id].u) {
155                     e[temp.id+1].used=0;
156                 } else e[temp.id-1].used=0;
157                 add(u,v,w,1);
158                 add(v,u,w,1);
159                 build();
160             }
161         } else {
162             long long a,b,c,d;
163             a=read(),b=read(),c=read(),d=read();
164             long long max1=lca(a,b).max,max2=lca(c,d).max;
165 //            cout<<"max1->"<<max1<<" max2->"<<max2<<" "<<'
';
166             if(max1^max2) {
167                 cout<<"madoka"<<'
';
168             } else {
169                 cout<<"Baozika"<<'
';
170             }
171         }
172     }
173     return 0;
174 }

over

原文地址:https://www.cnblogs.com/saionjisekai/p/9867132.html