BZOJ3498: PA2009 Cakes(三元環)
阿新 • • 發佈:2018-10-25
ons back turn href size 我們 lock ant push
題意
題目鏈接
Sol
按照套路把邊轉成無向圖,我們采取的策略是從權值大的向權值小的連邊
然後從按權值從小到大枚舉每個點,再枚舉他們連出去的點\(v\)
如果\(v\)的度數\(\leqslant M\),那麽就再暴力枚舉\(v\)連出去的點\(t\),看\(u\)與\(t\)是否聯通(打標記)
否則暴力枚舉\(u\)連出去的點\(t\),看\(v\)與\(t\)是否聯通(直接hash表)
復雜度為\(O(M \sqrt{M})\)
#include<bits/stdc++.h> #define LL long long using namespace std; const int MAXN = 100001; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N, M, a[MAXN], block, siz[MAXN], flag[MAXN], rak[MAXN], tp[MAXN]; vector<int> v[MAXN]; set<int> s[MAXN]; int comp(const int &x, const int &y) { return a[x] == a[y] ? x < y : a[x] < a[y]; } int main() { N = read(); M = read(); block = sqrt(M); for(int i = 1; i <= N; i++) a[i] = read(), tp[i] = i; sort(tp + 1, tp + N + 1, comp); for(int i = 1; i <= N; i++) rak[tp[i]] = i; for(int i = 1; i <= M; i++) { int x = read(), y = read(); if(rak[x] > rak[y]) v[x].push_back(y), siz[x]++; else v[y].push_back(x), siz[y]++; } LL ans = 0; for(int i = 3; i <= N; i++) { int x = tp[i]; for(int j = 0, to; j < v[x].size(); j++) flag[to = v[x][j]] = i; for(int j = 0, to; j < v[x].size(); j++) { if(siz[to = v[x][j]] <= block) { for(int k = 0; k < v[to].size(); k++) if(flag[v[to][k]] == i) ans += a[x]; } else { for(int k = 0; k < v[x].size(); k++) if(s[to].count(v[x][k])) ans += a[x]; } s[x].insert(to); } } cout << ans; return 0; } /* 2 1 13 17 2 1 */
BZOJ3498: PA2009 Cakes(三元環)