• ZOJ 3261 Connections in Galaxy War (逆向+带权并查集)


    题意:有N个星球,每个星球有自己的武力值。星球之间有M条无向边,连通的两个点可以相互呼叫支援,前提是对方的武力值要大于自己。当武力值最大的伙伴有多个时,选择编号最小的。有Q次操作,destroy为切断连接两点的边,query为查询某星球能不能向它人呼叫支援。

    还是需要离线逆向并查集求解。思路和HDU 4496很相似,但是此处不一定是把所有边都删去,所以需要删边的情况建立出最终的状态。因为N可以到1e4,所以可以用map嵌套map的方式记录过程中被删去的边,最后再根据删除情况建立状态。

    在合并时需要维护自己能够申请到的支援的武力最大值,以及其编号。

     1 #include<stdio.h>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cmath>
     6 #include<map>
     7 using namespace std;
     8 typedef long long LL;
     9 const int maxn = 2e4+5;
    10 const int INF= 0x3f3f3f3f;
    11 struct Edge{
    12     int u,v;
    13 }E[maxn];
    14 struct Query{
    15     int op,a,b;
    16     LL ans;
    17 }p[maxn*3];
    18 LL w[maxn];
    19 LL dist[maxn];
    20 int fa[maxn];
    21 int maxid[maxn];
    22 inline int Find(int x) {return fa[x]==x ?x: fa[x]=Find(fa[x]);}
    23 //void init(int N){ for(int i=0;i<N;++i) fa[i]=i,dist[i]=w[i],maxid[i]=i;}
    24 void Union(int a,int b){
    25     a = Find(a),b = Find(b);
    26     if(a!=b){
    27         fa[a] = b;
    28         if(dist[b]<dist[a] || dist[b]==dist[a] && maxid[b]>maxid[a]){
    29             dist[b]=dist[a];
    30             maxid[b]=  maxid[a];
    31         }
    32     }
    33 }
    34 
    35 map<int,map<int,int> > tag;
    36 
    37 int main()
    38 {
    39     #ifndef ONLINE_JUDGE
    40          freopen("in.txt","r",stdin);
    41          freopen("out.txt","w",stdout);
    42     #endif
    43     int T,N,M,Q,u,v,tmp,K,cas=1;
    44     char op[10];
    45     int mk = 0;
    46     while(scanf("%d",&N)==1){
    47         if(mk) printf("
    ");
    48         mk = 1;
    49         for(int i=0;i<N;++i) {
    50             scanf("%lld",&w[i]);
    51             fa[i]=maxid[i]=i;
    52             dist[i]=w[i];
    53         }
    54         tag.clear();
    55         scanf("%d",&M);
    56         for(int i=1;i<=M;++i){
    57             scanf("%d%d",&u,&v);
    58             E[i].u =u , E[i].v=v;
    59         }
    60         scanf("%d",&Q);
    61         for(int i=1;i<=Q;++i){
    62             scanf("%s%d",op,&p[i].a);
    63             if(op[0]=='d') {
    64                 p[i].op=0;
    65                 scanf("%d",&p[i].b);
    66                 tag[p[i].a][p[i].b]=tag[p[i].b][p[i].a]=1;                  //被删边的标记
    67             }
    68             else p[i].op = 1;                       //0删边,1查询
    69         }
    70         //因为并不是把边全删完,建立最终状态
    71         for(int i=1;i<=M;++i){
    72              if(tag[E[i].u][E[i].v]) continue;      //这条边不在
    73              else Union(E[i].u,E[i].v);
    74         }
    75 
    76         for(int i=Q;i>=1;--i){
    77             if(!p[i].op) Union(p[i].a,p[i].b); 
    78             else{
    79                 u = Find(p[i].a);
    80                 if(dist[u]>w[p[i].a]) p[i].ans=maxid[u];
    81                 else p[i].ans= -1;
    82             }    
    83         }
    84         for(int i=1;i<=Q;++i){
    85             if(p[i].op) printf("%lld
    ",p[i].ans);
    86         }
    87     }
    88     return 0;
    89 }
    为了更好的明天
  • 相关阅读:
    Eclipse Alt + / 无提示
    洛谷 P1101 单词方阵
    力扣题解 7th 整数反转
    力扣题解 344th 反转字符串
    力扣题解 48th 旋转图像
    力扣题解 36th 有效的数独
    力扣题解 1th 两数之和
    力扣题解 283th 移动零
    力扣题解 66th 加一
    力扣题解 350th 两个数组的交集 II
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9415716.html
Copyright © 2020-2023  润新知