oiwiki
#include <bits/stdc++.h>
using namespace std;
const int N = 400005;
typedef long long ll;
ll ans = 0;
int n, m, dfn[N], low[N], tot = 0, val[N], cnt = 0, stk[N], hh = 0, siz[N], sbn;
vector<int> g[N], t[N];
void tarjan(int x)
{
dfn[x] = low[x] = ++ tot;
stk[++ hh] = x;
val[x] = -1;
sbn ++;
for (int i = 0; i < g[x].size(); ++ i)
{
int y = g[x][i];
if(!dfn[y])
{
tarjan(y);
low[x] = min(low[x], low[y]);
if(low[y] >= dfn[x])
{
cnt ++;
int v = 0;
do
{
v = stk[hh --];
t[cnt].push_back(v);
t[v].push_back(cnt);
} while (v != y);
t[cnt].push_back(x);
t[x].push_back(cnt);
val[cnt] = t[cnt].size();
}
}
else low[x] = min(low[x], dfn[y]);
}
return ;
}
void dfs(int x, int fa)
{
if(x <= n) siz[x] = 1;
for (int i = 0; i < t[x].size(); ++ i)
{
int y = t[x][i];
if(y == fa) continue;
dfs(y, x);
ans = ans + (ll)val[x] * siz[x] * siz[y] * 2;
siz[x] += siz[y];
}
ans = ans + (ll)siz[x] * (sbn - siz[x]) * val[x] * 2;
}
int main()
{
scanf("%d %d", &n, &m);
cnt = n;
for (int i = 1; i <= m; ++ i)
{
int u, v;
scanf("%d %d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
for (int i = 1; i <= n; ++ i)
{
if(!dfn[i]) tarjan(i), hh --, dfs(i, 0), sbn = 0;
}
printf("%lld", ans);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
const int inf = 2000000000;
int n, m, q, tot = 0, cnt = 0, hh = 0, resg = -1, rest = -1, stk[N], dfn[N], low[N], val[N];
int top[N], dep[N], fa[N], son[N], fdfn[N], mn[N << 2];
multiset<int> ss[N];
int read()
{
int x = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}
struct edge
{
int to, nxt;
}t[1000005], g[1000005];
int headt[N], headg[N];
void add_edget(int u, int v)
{
t[++ rest].to = v, t[rest].nxt = headt[u], headt[u] = rest;
return ;
}
void add_edgeg(int u, int v)
{
g[++ resg].to = v, g[resg].nxt = headg[u], headg[u] = resg;
}
void tarjan(int x)
{
dfn[x] = low[x] = ++ tot;
stk[++ hh] = x;
for (int i = headg[x]; i != -1; i = g[i].nxt)
{
int y = g[i].to;
if(!dfn[y])
{
tarjan(y);
low[x] = min(low[x], low[y]);
if(low[y] >= dfn[x])
{
int v = 0;
cnt ++;
do
{
v = stk[hh --];
add_edget(cnt, v);
add_edget(v, cnt);
}while(v != y);
add_edget(cnt, x);
add_edget(x, cnt);
}
}
else low[x] = min(low[x], dfn[y]);
}
return ;
}
int dfs1(int x, int fa)
{
int siz = 1;
int maxsiz = 0;
for (int i = headt[x]; i != -1; i = t[i].nxt)
{
int y = t[i].to;
if(y == fa) continue;
int s = dfs1(y, x);
siz += s;
if(s > maxsiz) maxsiz = s, son[x] = y;
}
return siz;
}
void dfs2(int x, int v)
{
top[x] = v, dep[x] = dep[fa[x]] + 1, dfn[x] = ++ tot, fdfn[tot] = x;
if(son[x] <= n) ss[x].insert(val[son[x]]);
if(son[x]) fa[son[x]] = x, dfs2(son[x], v);
for (int i = headt[x]; i != -1; i = t[i].nxt)
{
int y = t[i].to;
if(dfn[y]) continue;
if(y <= n) ss[x].insert(val[y]);
fa[y] = x;
dfs2(y, y);
}
return ;
}
void build_tree(int p, int l, int r)
{
if(l == r)
{
if(fdfn[l] <= n) mn[p] = val[fdfn[l]];
else
{
auto it = ss[fdfn[l]].begin();
mn[p] = *it;
}
return ;
}
int mid = l + r >> 1;
build_tree(p << 1, l, mid);
build_tree(p << 1 | 1, mid + 1, r);
mn[p] = min(mn[p << 1], mn[p << 1 | 1]);
return ;
}
void update(int p, int l, int r, int x, int k)
{
if(l == r)
{
mn[p] = k;
return ;
}
int mid = l + r >> 1;
if(x <= mid) update(p << 1, l, mid, x, k);
else update(p << 1 | 1, mid + 1, r, x, k);
mn[p] = min(mn[p << 1], mn[p << 1 | 1]);
return ;
}
int query(int p, int l, int r, int L, int R)
{
if(L <= l && r <= R) return mn[p];
if(l > R || r < L) return inf;
int mid = l + r >> 1;
return min(query(p << 1, l, mid, L, R), query(p << 1 | 1, mid + 1, r, L, R));
}
int get_path(int a, int b)
{
int ans = inf;
while(top[a] != top[b])
{
if(dep[top[a]] < dep[top[b]]) swap(a, b);
ans = min(ans, query(1, 1, cnt, dfn[top[a]], dfn[a]));
a = fa[top[a]];
}
if(dep[a] > dep[b]) swap(a, b);
ans = min(ans, query(1, 1, cnt, dfn[a], dfn[b]));
if(a > n) ans = min(ans, val[fa[a]]);
return ans;
}
int main()
{
memset(headt, -1, sizeof headt);
memset(headg, -1, sizeof headg);
n = read(), m = read(), q = read();
cnt = n;
for (int i = 1; i <= n; ++ i) val[i] = inf;
for (int i = 1; i <= n; ++ i) val[i] = read();
for (int i = 1; i <= m; ++ i)
{
int u, v;
scanf("%d %d", &u, &v);
add_edgeg(u, v), add_edgeg(v, u);
}
tarjan(1);
tot = 0;
for (int i = 1; i <= n + n; ++ i) dfn[i] = 0;
dfs1(1, 0);
dfs2(1, 1);
build_tree(1, 1, cnt);
while(q --)
{
char s[3];
scanf("%s", s + 1);
if(s[1] == 'C')
{
int a, w;
a = read(), w = read();
if(a > 1 && a <= n)
{
int y = fa[a];
auto it = ss[y].lower_bound(val[a]);
ss[y].erase(it);
ss[y].insert(w);
it = ss[y].begin();
update(1, 1, cnt, dfn[y], *it);
}
update(1, 1, cnt, dfn[a], w);
val[a] = w;
}
else
{
int a, b;
a = read(), b = read();
printf("%d\n", get_path(a, b));
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!