zoj 3261 逆向并查集+离线处理

题意:给出一些点,每个点有权值,然后有一些边,相连。无向的。然后有一些操作

链接:点我

query a.表示从a出发的能到达的所有点权值最大的点的编号(相同取编号最小,而且权值要比自己大)

destory a,b 表示删除连接a,b的边

逆向并查集。

把没有删除的边先加入并查集,一个集合内表示连通的,根结点为权值最大的点。

然后对于查询离线读入,从最后开始操作,对于删除的点,然后重新加入到并查集中,更新最值。

查询的时候便是查询根结点的值是否大于自身的值

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <map>
  6 using namespace std;
  7 
  8 const int MAXN=10010;
  9 int F[MAXN];
 10 int p[MAXN];
 11 int val[MAXN];//最大值的下标
 12 int num[MAXN];//最大值
 13 int find(int x)
 14 {
 15     if(F[x]==-1)return x;
 16     return F[x]=find(F[x]);
 17 }
 18 void bing(int u,int v)
 19 {
 20     int t1=find(u),t2=find(v);
 21     if(t1!=t2)
 22     {
 23         F[t1]=t2;
 24         if(num[t1]>num[t2])
 25         {
 26             num[t2]=num[t1];
 27             val[t2]=val[t1];
 28         }
 29         else if(num[t1]==num[t2] && val[t2]>val[t1])
 30             val[t2]=val[t1];
 31     }
 32 }
 33 map<int,int>mp[MAXN];
 34 struct Edge
 35 {
 36     int u,v;
 37 }edge[20010];
 38 bool used[20010];
 39 struct Node
 40 {
 41     int op;
 42     int u,v;
 43 }node[50010];
 44 int ans[50010];
 45 char str[20];
 46 int main()
 47 {
 48     int n;
 49     int Q;
 50     int m;
 51     int u,v;
 52     bool first=true;
 53     while(scanf("%d",&n)==1)
 54     {
 55         if(first)first=false;
 56         else printf("
");
 57         memset(F,-1,sizeof(F));
 58         for(int i=0;i<n;i++)
 59         {
 60             scanf("%d",&p[i]);
 61             val[i]=i;
 62             num[i]=p[i];
 63             mp[i].clear();
 64         }
 65 
 66         scanf("%d",&m);
 67         for(int i=0;i<m;i++)
 68         {
 69             scanf("%d%d",&u,&v);
 70             if(u>v)swap(u,v);
 71             mp[u][v]=i;
 72             edge[i].u=u;
 73             edge[i].v=v;
 74             used[i]=false;
 75         }
 76         scanf("%d",&Q);
 77         for(int i=0;i<Q;i++)
 78         {
 79             scanf("%s",&str);
 80             if(str[0]=='q')
 81             {
 82                 node[i].op=0;
 83                 scanf("%d",&node[i].u);
 84             }
 85             else
 86             {
 87                 node[i].op=1;
 88                 scanf("%d%d",&u,&v);
 89                 if(u>v)swap(u,v);
 90                 node[i].u=u;
 91                 node[i].v=v;
 92                 int tmp=mp[u][v];
 93                 used[tmp]=true;
 94             }
 95         }
 96         for(int i=0;i<m;i++)    //没有拆的点连上
 97           if(!used[i])
 98           {
 99               bing(edge[i].u,edge[i].v);
100           }
101         int cnt=0;
102         for(int i=Q-1;i>=0;i--)
103         {
104             if(node[i].op==0)
105             {
106                 u=node[i].u;
107                 int t1=find(u);
108                 if(num[t1]>p[u])ans[cnt++]=val[t1];
109                 else ans[cnt++]=-1;
110             }
111             else
112             {
113                 bing(node[i].u,node[i].v);
114             }
115         }
116         for(int i=cnt-1;i>=0;i--)printf("%d
",ans[i]);
117     }
118     return 0;
119 }
原文地址:https://www.cnblogs.com/cnblogs321114287/p/4487753.html