题意
n
点,
题解
按照题解,对每一种颜色建并查集,询问时找颜色较少的一端枚举所有颜色看是否与另一端点连通,并记录答案,复杂度 O(mq√logm)
代码
/// by ztx
#include <cstdio>
#include <map>
#include <vector>
#include <algorithm>
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i<(r);i++)
#define maxn 100010LL
#define maxm 100010LL
#define PII std::pair<int,int>
#define Pair std::make_pair
struct Block {
int col, sz;
Block *fa;
Block() { fa = NULL, sz = 1; }
Block(int col=0,int sz=1,Block*fa=NULL) { this->col = col, this->sz = sz, this->fa = fa;}
bool operator < (const Block&B) const { return col < B.col; }
bool operator == (const Block&B) const { return col == B.col; }
};
inline Block *GetAnc(Block *u) { return u->fa ? u->fa = GetAnc(u->fa) : u; }
inline void Union(Block *u, Block *v) {
u = GetAnc(u), v = GetAnc(v);
if (u == v) return ;
if (u->sz < v->sz) std::swap(u,v);
v->fa = u, u->sz += v->sz;
}
inline bool Connect(Block *u, Block *v) {
if (u == NULL || v == NULL) return false;
u = GetAnc(u), v = GetAnc(v);
return u == v;
}
int a[maxm], b[maxm], c[maxm];
std::vector<Block>col[maxn];
int Get_tmp;
inline Block *Get(int p,int c) {
Get_tmp = std::lower_bound(col[p].begin(),col[p].end(),(Block){c})-col[p].begin();
return Get_tmp<col[p].size() ? &col[p][Get_tmp] : NULL;
}
std::map<PII,int>mp;
int main() {
int n, m, i, q, u, v, ans;
Block *w;
scanf("%d%d", &n, &m);
Rep (i,1,m) {
scanf("%d%d%d", &a[i], &b[i], &c[i]);
col[a[i]].push_back((Block){c[i]}), col[b[i]].push_back((Block){c[i]});
}
Rep (i,1,n) {
std::sort(col[i].begin(),col[i].end());
col[i].erase(std::unique(col[i].begin(),col[i].end()),col[i].end());
}
Rep (i,1,m)
Union(Get(a[i],c[i]),Get(b[i],c[i]));
scanf("%d", &q);
while (q --> 0) {
scanf("%d%d", &u, &v);
ans = 0;
if (col[u].size() > col[v].size()) std::swap(u,v);
if (mp.find(Pair(u,v)) == mp.end()) {
rep (i,0,col[u].size()) {
w = &col[u][i];
if (Connect(w,Get(v,w->col)))
ans ++ ;
}
mp[Pair(u,v)] = ans;
} else ans = mp[Pair(u,v)];
printf("%d\n", ans);
}
getchar(), getchar();
return 0;
}