题目链接
思路:
关于静态仙人掌的问题,建立出圆方树比较好求解。求出来之后处理每个圆点方点的情况,原来的是树边直接处理,环边的话方点连向环上每个圆点一条边,权值为每个节点到环的父亲节点的最短距离。然后倍增预处理,查询的时候,如果
lca
l
c
a
是圆点直接输出,否则两个点是环上的点,处理他们在环上的最短距离即可。
为啥我的代码都这么慢啊。。。加了输入输出挂还900ms。。别人的什么都不做都400ms。。。
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 1e5 + 10;
using namespace std;
struct edge {
int u, v, cost;
edge(int u = 0, int v = 0, int cost = 0) : u(u), v(v), cost(cost) {}
};
int n, m, T, kase = 1, q;
vector<int> G[maxn], bcc[maxn], w[maxn];
int dp[maxn][2], dfn[maxn], dfs_clock, tot;
int pre[maxn], bccno[maxn], bcc_cnt, stk[maxn][2];
vector<int> et[maxn], ew[maxn];
int rec_cost[maxn], deep[maxn], ds[maxn];
stack<edge> S;
const int hash_size = 1e6 + 10;
int head[hash_size], nxt[hash_size], vt[hash_size], tt[hash_size], key[hash_size], top;
int anc[maxn][15], cost[maxn][15];
void insert(int u, int t, int val) {
int x = u * (maxn / 10) + t;
x = x % hash_size;
nxt[top] = head[x];
head[x] = top;
vt[top] = u;
tt[top] = t;
key[top] = val;
top++;
}
int ask(int u, int t) {
int x = u * (maxn / 10) + t;
x = x % hash_size;
int nn = head[x];
while(~nn) { if(vt[nn] == u && tt[nn] == t) return key[nn]; nn = nxt[nn]; }
return 0;
}
int dfs(int u, int fa) {
int lowu = pre[u] = ++dfs_clock, child = 0;
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i], co = w[u][i];
edge e = edge(u, v, co);
if(!pre[v]) {
S.push(e); child++;
int lowv = dfs(v, u);
lowu = min(lowu, lowv);
if(lowv >= pre[u]) {
bcc_cnt++; bcc[bcc_cnt].clear();
int tot_dis = 0, cnt = 0;
while(1) {
edge x = S.top(); S.pop();
rec_cost[cnt++] = x.cost;
tot_dis += x.cost;
if(bccno[x.v] != bcc_cnt) { bcc[bcc_cnt].push_back(x.v); bccno[x.v] = bcc_cnt; }
if(bccno[x.u] != bcc_cnt) { bcc[bcc_cnt].push_back(x.u); bccno[x.u] = bcc_cnt; }
if(x.u == u && x.v == v) break;
}
if(bcc[bcc_cnt].size() == 2) {
et[u].push_back(v); //树边
et[v].push_back(u);
ew[u].push_back(co);
ew[v].push_back(co);
} else {
tot++; int dis = 0; ds[tot] = tot_dis;
for(int i = 0; i < bcc[bcc_cnt].size(); i++) {
int v = bcc[bcc_cnt][i];
et[v].push_back(tot);
et[tot].push_back(v);
if(!i) {
ew[v].push_back(0); ew[tot].push_back(0);
insert(v, tot, dis);
} else {
insert(v, tot, dis);
int min_dis = min(dis, tot_dis - dis);
ew[v].push_back(min_dis);
ew[tot].push_back(min_dis);
}
dis += rec_cost[i];
}
}
}
} else if(pre[v] < pre[u] && v != fa) {
S.push(e); lowu = min(lowu, pre[v]);
}
}
return lowu;
}
const int MAX = 10000;
char buf[MAX], *ps = buf, *pe = buf + 1;
inline void rnext() {
if(++ps == pe) pe = (ps = buf) + fread(buf, sizeof(char), sizeof(buf) / sizeof(char), stdin);
}
template <class T>
inline bool in(T &ans) {
ans = 0;
T f = 1;
if(ps == pe) return false;//EOF
do{
rnext();
if('-' == *ps) f = -1;
} while(!isdigit(*ps) && ps != pe);
if(ps == pe) return false;//EOF
do {
ans = (ans<<1)+(ans<<3)+*ps-48;
rnext();
} while(isdigit(*ps) && ps != pe);
ans *= f;
return true;
}
void DFS(int x, int fa, int co, int d) {
anc[x][0] = fa; cost[x][0] = co; deep[x] = d;
for(int i = 1; i < 15; i++) {
int t = anc[x][i - 1];
if(~t) { anc[x][i] = anc[t][i - 1]; cost[x][i] = cost[x][i - 1] + cost[t][i - 1]; }
else break;
}
for(int i = 0; i < et[x].size(); i++) {
int v = et[x][i];
int c = ew[x][i];
if(v != fa) DFS(v, x, c, d + 1);
}
}
inline int query(int x, int y) {
int ans = 0;
if(deep[x] < deep[y]) swap(x, y);
for(int i = 14; i >= 0; i--) {
if(deep[x] - (1 << i) < deep[y]) continue;
ans += cost[x][i]; x = anc[x][i];
}
if(x == y) return ans;
for(int i = 14; i >= 0; i--) {
if(anc[x][i] == anc[y][i]) continue;
ans += cost[x][i]; ans += cost[y][i];
x = anc[x][i]; y = anc[y][i];
}
if(anc[x][0] > n) {
int px = anc[x][0], tot_dis = ds[px];
int now_dis = abs(ask(x, px) - ask(y, px));
ans += min(now_dis, tot_dis - now_dis);
} else ans += cost[x][0] + cost[y][0];
return ans;
}
char bufout[MAX], outtmp[50],*pout = bufout, *pend = bufout + MAX;
inline void write() {
fwrite(bufout, sizeof(char), pout - bufout, stdout);
pout = bufout;
}
inline void out_char(char c) { *(pout++) = c; if(pout == pend) write(); }
inline void out_str(char *s) {
while(*s) {
*(pout++) = *(s++);
if(pout == pend) write();
}
}
template <class T>
inline void out_int(T x) {
if(!x) {
out_char('0');
return;
}
if(x < 0) x = -x,out_char('-');
int len = 0;
while(x) {
outtmp[len++] = x%10+48;
x /= 10;
}
outtmp[len] = 0;
for(int i = 0, j = len - 1; i < j; i++,j--) swap(outtmp[i],outtmp[j]);
out_str(outtmp);
}
int main() {
// ios::sync_with_stdio(0);
// freopen("in.txt", "r", stdin);
// freopen("wa.txt", "w", stdout);
memset(head, -1, sizeof head);
memset(nxt, -1, sizeof nxt);
// cin >> n >> m >> q;
in(n); in(m); in(q);
for(int i = 1; i <= m; i++) {
int u, v, c; //cin >> u >> v >> c;
in(u); in(v); in(c);
G[u].push_back(v);
w[u].push_back(c);
G[v].push_back(u);
w[v].push_back(c);
}
tot = n;
memset(anc, -1, sizeof anc);
dfs(1, -1); DFS(1, -1, 0, 1);
while(q--) {
int u, v;
//cin >> u >> v;
in(u); in(v);
int ans = query(u, v);
//cout << ans << endl;
//printf("%d\n", ans);
out_int(ans); out_char('\n');
}
write();
return 0;
}