不同的结构形成的结果也不同。。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#define MAXN 200010
using namespace std;
int n,m,fa[MAXN*2],key[MAXN*2],ans,out[MAXN*2],anss,k,t=1,a,b;
vector<int > G[MAXN*2];//不开大会RE的
stack<int > s;
inline int read()//读入优化
{
int s=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){s=s*10+c-'0';c=getchar();}
return s*f;
}
int find(int x)//并查集
{
if(fa[x]!=x)
{
fa[x]=find(fa[x]); //路径压缩
}
return fa[x];
}
int onion(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx!=fy)
{
ans++;//当两个元素不在同一个集合中的时候 用ans记录一下减少了几个联通块
//也就是说每当有两个不同的集合被合并的时候 联通块数量-1
fa[fx]=fy;
}
}
void init()//输入
{
memset(key,1,sizeof(key));
n=read();m=read();
for(int i=0;i<n;i++)
{
fa[i]=i;
}
for(int i=0;i<m;i++)
{
a=read();b=read();
G[a].push_back(b);//双向存边
G[b].push_back(a);
}
}
void pre()//预处理
{
k=read();
for(int i=0;i<k;i++)
{
a=read();
s.push(a);//因为要倒序加入 所以就写了个栈 STL 大法好啊
key[a]=0;//记录一下哪些点要被删除 然后标记一下
}
for(int i=0;i<n;i++)
{
if(key[i])
{
for(int j=0;j<G[i].size();j++)//将所有剩余的点跑一次并查集
{
int v=G[i][j];
if(key[v])//如果相连的另一个点不在图中 就不能加入
{
onion(i,v);
}
}
}
}
anss=n-k-ans;ans=0;out[k]=anss;//这时候算的是最后一个数据 也就是所有的边都被删之后剩余联通块数
//用anss记录剩余联通块 n-k-ans就是n-k个元素减去联通块减少的数量 就是剩余的数量了
}
void work()
{
while(!s.empty())//倒序加入
{
int v=s.top();s.pop();
for(int j=0;j<G[v].size();j++)
{
int dd=G[v][j];
if(key[dd])//还是判断一下是否在图中
{
onion(dd,v);
}
}
anss=anss-ans+1;//因为一个新的点加入之后 本身联通块就要多一个 所以这里不是anss-ans而是anss-ans+1
out[k-t]=anss;//记录
ans=0;t++;key[v]=1; //每次记得要把ans清零 还有key【v】为true 也就是这个点已经加入到图中了
}
}
void outit()
{
for(int i=0;i<=k;i++)
{
cout<<out[i]<<endl; //我是倒序保存然后正序输出的 正序保存倒序输出也ok
}
}
int main()
{
std::ios::sync_with_stdio(false);//如果不用scanf的话记得开优化 不然有一个点会TLE的
std::cin.tie(0);//其实就是因为我不用链表存 而是用vector 所以才慢的
init();
pre();
work();
outit();
return 0;
}
我的代码只通过了50%..
#include <bits/stdc++.h>
using namespace std;
int n,m;
int k;
int const maxn =400010;
int f[maxn],vis[maxn];
int cnn;
struct Edge {
int from,to;
Edge(int _from,int _to):from(_from),to(_to){}
};
queue<Edge> all,res;
stack<int> ans;
stack<int> star;
vector<Edge> edges;
vector<int> G[maxn],G2[maxn];
int find_f(int x) {
return f[x]!=x?f[x]=find_f(f[x]):x;
}
void add_edges(int from,int to)
{
Edge e1(from,to),e2(to,from);
edges.push_back(e1);
G[e1.from].push_back(edges.size()-1);
edges.push_back(e2);
G[e2.from].push_back(edges.size()-1);
}
void union_set(int x,int y) {
int rx = find_f(x);
int ry = find_f(y);
if(rx!=ry) {
f[ry] = rx;
cnn--;
}
}
bool query(int x,int y){
int rx = find_f(x);
int ry = find_f(y);
if(rx!=ry) return false;
return true;
}
void work() {
int label = star.top();
star.pop();
if(label==-1) {
stack<int> tt=star;
set<int> s;
while(!tt.empty())
{
int temp = tt.top();tt.pop();
for(int i=0;i<G[temp].size();i++) {
s.insert(G[temp][i]);
s.insert(G[temp][i]^1);
}
}
for (int i=0;i<edges.size();i+=2)
{
if(s.count(i)==0) union_set(edges[i].from,edges[i].to);
}
return;
}
vis[label] = 1;
for(int i=0;i<G[label].size();i++)
{
Edge e1 = edges[G[label][i]];
Edge e2 = edges[G[label][i]^1];
if(vis[e1.to]) {
union_set(e1.from,e1.to);
}
if(vis[e2.from]) {
union_set(e2.from,e2.to);
}
}
}
int main() {
// freopen("in.txt","r",stdin);
std::ios::sync_with_stdio(false);//如果不用scanf的话记得开优化 不然有一个点会TLE的
std::cin.tie(0);//其实就是因为我不用链表存 而是用vector 所以才慢的
cin>>n>>m;
int fo,t;
for (int i=0;i<m;i++)
{
cin>>fo>>t;
add_edges(fo,t);
}
cin>>k;
cnn=n;
for (int i=0;i<n;i++) {
vis[i] = 1;
f[i] = i;
}
for (int i=0;i<k;i++)
{
cin>>fo;
vis[fo] = 0;
star.push(fo);
}
star.push(-1);
while(!star.empty())
{
work();
ans.push(cnn-star.size());
}
while(!ans.empty())
{
cout<<ans.top()<<endl;
ans.pop();
}
}