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("\n");

 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\n",ans[i]);

117     }

118     return 0;

119 }

 

你可能感兴趣的:(并查集)