Where are you - 牛客
阿新 • • 發佈:2018-12-08
題意
\(n\)個點\(m\)條帶權邊的無向連通圖\(G\),記\(G\)的最小生成樹集合\(minTree\),求滿足\(edge \in minTree_i(1\leq i \leq size(minTree))\)的條數。(既這條邊要在\(G\)的所有最小生成樹中出現)
\(2 \leq n <m\leq2* 10^5\),\(1 \leq w \leq 10^6\)
題解
考慮相同權值的邊對最小生成樹造成的影響。將邊排序後,記\(w_i\)為當前要加的邊的權值,\(G’\)為使用權值\(w_j(1\leq j \leq i - 1)\)的邊依照kruskal演算法構成的圖。那麼向\(G'\)
1.\(G'\)可能有很多個,那麼選擇某個\(G'\)是否對\(G''\)的橋的個數會有影響?
不會,記權值為\(w_i\)的邊的兩個端點為\(u,v\),\(G'\)的頂點集合為\(S\),如果\(u \in S, v \in S\),那麼無論是哪個\(G'\),這條邊都不會加入\(G'\)去構成\(G''\)。如果不都屬於\(S\),那麼這條邊與\(G'\)中邊沒有任何關係,既無論是哪個\(G'\)都不會對\(G''\)造成影響。
2.如果每加入一組權值為\(w_i\)
顯然會超時,由1得,新加的邊與\(G'\)沒有關係,所以可以將\(G'\)的各個連通分支壓縮成一個點。然後建圖,跑完Tarjan,再刪除原來的圖。
程式碼
const int N = 200050; struct Edge { int u, v, w; } e[N]; struct node { int to, next, id; } G[N << 1]; int n, m, p, tot, cnt; int fa[N], Low[N], Dfn[N], res[N], head[N]; bool cmp(Edge& a, Edge& b) { return a.w < b.w; } void Inite() { cnt = tot = 0; mem(head, -1); rep(i, 1, N) fa[i] = i; } void addedge(int u, int v, int id) { G[tot].to = v, G[tot].id = id, G[tot].next = head[u], head[u] = tot++; G[tot].to = u, G[tot].id = id, G[tot].next = head[v], head[v] = tot++; } void Tarjan(int u, int last) { Low[u] = Dfn[u] = ++cnt; for (int i = head[u]; ~i; i = G[i].next) if (i != (1 ^ last)) { int v = G[i].to; if (Dfn[v]) Low[u] = min(Low[u], Dfn[v]); else { Tarjan(v, i); Low[u] = min(Low[u], Low[v]); if (Dfn[u] < Low[v]) res[G[i].id] = 1; } } } int Find(int a) { return (a == fa[a] ? a : (fa[a] = Find(fa[a]))); } void Solve() { for (int i = 1, j = 1; i <= m; i = j, tot = 0) { while(e[j].w == e[i].w) ++j; rep(k, i, j) { int fu = Find(e[k].u), fv = Find(e[k].v); if (fu != fv) addedge(fu, fv, k); } rep(k, i, j) { int fu = Find(e[k].u), fv = Find(e[k].v); if ((fu != fv) && !Dfn[fu]) Tarjan(fu, -1); } rep(k, i, j) { int fu = Find(e[k].u), fv = Find(e[k].v); Dfn[fu] = Dfn[fv] = 0; head[fu] = head[fv] = -1; if (fu != fv) fa[fu] = fv; } } int ans = 0; Rep(i, 1, m) ans += res[i]; pr(ans); } int main() { Inite(); IOS; cin >> n >> m >> p; Rep(i, 1, m) cin >> e[i].u >> e[i].v >> e[i].w; sort(e + 1, e + m + 1, cmp); Solve(); return 0; }