题解:先scc把图变成树, 然后对于这若干棵树在进行dsu的操作。
dsu就是先找到最大的子树放在一边,然后先处理小的子树,最后处理大的子树。无限递归。
重要的一点就是 是否重新添加每个点的值,每次处理完小的子树之后会清空影响,然后处理完最大的子树之后就不再清空影响,这样减少复杂度。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL mod = (int)1e9+7; const int N = 2e5 + 100; int head[N], to[N<<1], nt[N<<1], tot = 0; void add(int u, int v){ to[tot] = v; nt[tot] = head[u]; head[u] = tot++; } int belong[N], dfn[N], low[N], now_time, scc_cnt; int now = 0, st[N], ed[N]; vector<int> vc[N]; vector<pll> e[N]; stack<int> s; void dfs(int u, int id){ dfn[u] = low[u] = ++now_time; s.push(u); for(int i = head[u]; ~i; i = nt[i]){ if(i == (id^1)) continue; if(!dfn[to[i]]) dfs(to[i], i); if(!belong[to[i]]) low[u] = min(low[u], low[to[i]]); } if(dfn[u] == low[u]){ ++scc_cnt; int now; while(1){ now = s.top(); s.pop(); belong[now] = scc_cnt; vc[scc_cnt].pb(now); if(now == u) break; } } } void scc(int n){ for(int i = 1; i <= scc_cnt; ++i) { vc[i].clear(); e[i].clear(); st[i] = ed[i] = 0; } now = 0; for(int i = 1; i <= n; ++i) dfn[i] = low[i] = belong[i] = 0; while(!s.empty()) s.pop(); now_time = scc_cnt = 0; for(int i = 1; i <= n; ++i) if(!belong[i]) dfs(i,-1); for(int i = 0, u, v; i <= tot; i += 2){ u = to[i], v = to[i+1]; u = belong[u], v = belong[v]; if(u != v) e[u].pb(pll(v,i/2+1)), e[v].pb(pll(u,i/2+1)); } } int vis[N], col[N], col2[N], cnt[N], cnt2[N], mx1, mx2; int sz[N], p[N]; int a[N]; void Add1(int u){ for(int i = 0, x; i < vc[u].size(); ++i){ x = vc[u][i]; cnt[col[a[x]]]--; ++col[a[x]]; cnt[col[a[x]]]++; if(mx1 < col[a[x]]) mx1 = col[a[x]]; } } void Add2(int u){ for(int i = 0, x; i < vc[u].size(); ++i){ x = vc[u][i]; cnt2[col2[a[x]]]--; ++col2[a[x]]; cnt2[col2[a[x]]]++; if(mx2 < col2[a[x]]) mx2 = col2[a[x]]; } } void Sub1(int u){ for(int i = 0, x; i < vc[u].size(); ++i){ x = vc[u][i]; --cnt[col[a[x]]]; --col[a[x]]; ++cnt[col[a[x]]]; if(cnt[mx1] == 0) --mx1; } } void Sub2(int u){ for(int i = 0, x; i < vc[u].size(); ++i){ x = vc[u][i]; --cnt2[col2[a[x]]]; --col2[a[x]]; ++cnt2[col2[a[x]]]; if(cnt2[mx2] == 0) --mx2; } } void ddfs(int o, int u){ //cout << o << ' ' << u << endl; ++now; Add1(u); p[now] = u; st[u] = now; sz[u] = vc[u].size(); for(int i = 0, v; i < e[u].size(); ++i){ v = e[u][i].fi; if(v == o) continue; ddfs(u, v); sz[u] += sz[v]; } ed[u] = now; } void Clear(int o, int u){ Sub1(u); for(int i = 0; i < e[u].size(); ++i){ int v = e[u][i].fi; if(v == o) continue; Clear(u, v); } } int ttttmp; int val[N]; void dsu(int o, int u, int op, int id){ int bigson = -1, mx = -1, iid; for(int i = 0, v; i < e[u].size(); ++i){ v = e[u][i].fi; if(v == o) continue; if(mx < sz[v]) { mx = sz[v]; bigson = v; iid = e[u][i].se; } } for(int i = 0, v; i < e[u].size(); ++i){ v = e[u][i].fi; if(v == o || v == bigson) continue; dsu(u, v, 0, e[u][i].se); } if(bigson != -1) dsu(u, bigson, 1, iid); for(int i = 0, v; i < e[u].size(); ++i){ v = e[u][i].fi; if(v != o && v != bigson) { for(int i = st[v]; i <= ed[v]; i++){ Sub1(p[i]); Add2(p[i]); } } } Sub1(u); Add2(u); val[id] = mx1+mx2-ttttmp; if(op == 0){ for(int i = st[u]; i <= ed[u]; i++){ Sub2(p[i]); Add1(p[i]); } } } void init(){ memset(head, -1, sizeof(head)); tot = 0; } int main(){ int T, n, m; scanf("%d", &T); while(T--){ init(); scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); for(int i = 1, u, v; i <= m; ++i){ scanf("%d%d", &u, &v); add(u,v); add(v,u); } scc(n); int ans = 0; for(int i = 1; i <= scc_cnt; ++i){ if(st[i]) continue; mx1 = mx2 = 0; ddfs(0,i); ttttmp = mx1; ans += mx1; dsu(0,i,0,0); Clear(0,i); } // cout << ans << endl; for(int i = 1; i <= m; i++){ printf("%d%c", ans+val[i]," "[i==m]); val[i] = 0; } } return 0; } /* 3 7 5 1 2 1 2 1 2 1 1 2 1 3 2 4 5 6 5 7 3 3 1 2 3 1 2 1 3 2 3 7 5 1 2 1 2 1 2 1 1 2 1 3 2 4 5 6 5 7 */