星球大战——我总算知道为什么大神写并查集不用Union 函数而是在主函数里直接写了

  cnt 的计算问题。我先是每次询问都一次扫合格点,正确性没有问题,但是疯狂超时,理所当然啊N*M。然后用了直接一个cnt 记录的办法,样例刚开始的几个结点计算的好好的,但是当所有星球都快要恢复边完成的时候图就会变成一大个联通分量,cnt 就往负数减下去。我傻逼地加了个if(cnt>1) 才递减的特判,虽然样例过了,但提交肯定会WA 成一片,所以就搜了题解……然后看到了大神的代码,恍然大悟。最终如下:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<string>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<stack>
 9 #include<queue>
10 #include<cmath>
11 #include<map>
12 #include<set>
13 using namespace std;
14 const int N=4194304;
15 int n,m,qn,cnt,val[N],fth[N],res[N];
16 bool vis[N];
17 vector<int> gr[N];
18 int fnd(int x){return x==fth[x]?x:fth[x]=fnd(fth[x]);}
19 int main(){
20     for(int i=0;i<N;i++)fth[i]=i;
21     freopen("zenith.txt","r",stdin);
22     cin>>n>>m;cnt=n;
23     for(int i=1;i<=m;i++){
24         int x,y;scanf("%d%d",&x,&y);
25         gr[x].push_back(y);gr[y].push_back(x);
26     }
27     cin>>qn;
28     for(int i=1;i<=qn;i++){
29         scanf("%d",val+i);
30         vis[val[i]]=true;
31         cnt--;
32     }
33     for(int i=0;i<n;i++)
34         if(!vis[i]){
35             for(int j=0;j<gr[i].size();j++)
36                 if(!vis[gr[i][j]]){
37                     int t1=fnd(i),t2=fnd(gr[i][j]);
38                     if(t1!=t2)fth[t2]=t1,cnt--;
39                 }
40         }
41     res[qn+1]=cnt;
42     for(int k=qn;k>=1;k--){
43         int x=val[k];
44         vis[x]=false;
45         cnt++;
46         for(int i=0;i<gr[x].size();i++)
47             if(!vis[gr[x][i]]){
48                 int t1=fnd(x),t2=fnd(gr[x][i]);
49                 if(t1!=t2)fth[t2]=t1,cnt--;
50             }
51         res[k]=cnt;
52     }
53     for(int i=1;i<=qn+1;i++)printf("%d\n",res[i]);
54     return 0;
55 }
Method_01

  洛谷 BanG Dream! 3144ms 

posted @ 2017-08-25 22:33  Darkins  阅读(220)  评论(0)    收藏  举报