q个操作,每次将和 o i o_i oi相连的点都染成和 o i o_i oi一样的颜色,求最终每个点所属的集合。 ( n , q ≤ 2 × 1 0 5 ) (n,q\leq2\times10^5) (n,q≤2×105)
重要观察:只要一个点被归入一个集合,他们之后是一直相连的。
用一个链表存储所有与 u i u_i ui相连的点,每次将所有与 e [ o i ] e[o_i] e[oi]中的点相连的点都染入 o i o_i oi的集合即可。
#include
#define mem(ss) memset(ss,0,sizeof(ss))
#define rep(d, s, t) for(int d=s;d<=t;d++)
#define rev(d, s, t) for(int d=s;d>=t;d--)
#define inf 0x3f3f3f3f
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef double db;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
typedef std::pair<double, double> pdd;
const double eps = 1e-6;
const ll mod = 1e9 + 7;
const int N = 8e5 + 10;
#define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
int fa[N];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
vector<int> e[N];
int main() {
io_opt;
int t;
cin >> t;
while (t--) {
int n, m;
cin>>n>>m;
for (int i = 0; i < n; i++) {
fa[i] = i;
e[i].clear();
}
while (m--) {
int x, y;
cin>>x>>y;
e[x].push_back(y);
e[y].push_back(x);
}
int q;
cin>>q;
while (q--) {
int o;
cin>>o;
if (find(o) == o) {
vector<int> p = e[o];
e[o].clear();
for (int i : p) {
int u = find(i);
if (u != o) {
fa[u] = o;
if(e[o].size() < e[u].size()) swap(e[u],e[o]);//不这样写会莫名MLE
for (int j : e[u])
e[o].push_back(j);
}
}
}
}
for (int i = 0; i < n; i++)
cout << find(i)<<' ';
cout<<endl;
}
return 0;
}