【HDOJ】3686 Traffic Real Time Query System

这题做了几个小时,基本思路肯定是求两点路径中的割点数目,思路是tarjan缩点,然后以割点和连通块作为新节点见图。转化为lca求解。
结合点——双连通分量与LCA。

 /* 3686 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 typedef struct {
int u, v, f, nxt;
} edge_t; typedef struct {
int v, nxt;
} edge; const int maxv = ;
const int maxe = ;
int head[maxv], l, top;
int pre[maxv], low[maxv];
bool iscut[maxv];
int cnt[maxv], dfs_clock, bcc_cnt;
int bn[maxe];
int S[maxe];
vi bcc[maxv];
edge_t E[maxe];
int n, m; const int maxvv = maxv * ;
int mark[maxvv];
int head_[maxvv], l_;
int cutn[maxvv];
edge E_[maxe]; int deep[maxvv], beg[maxvv];
int V[maxvv<<], D[maxvv<<]; int dp[][maxvv<<]; void init_() {
memset(head_, -, sizeof(head_));
memset(mark, , sizeof(mark));
l_ = ;
} void addEdge_(int u, int v) {
E_[l_].v = v;
E_[l_].nxt = head_[u];
head_[u] = l_++; E_[l_].v = u;
E_[l_].nxt = head_[v];
head_[v] = l_++;
} void init() {
l = dfs_clock = bcc_cnt = top = ;
memset(head, -, sizeof(head));
memset(iscut, false, sizeof(iscut));
memset(cnt, , sizeof(cnt));
memset(cutn, , sizeof(cutn));
memset(pre, , sizeof(pre));
rep(i, , n+)
bcc[i].clr();
} void addEdge(int u, int v) {
E[l].u = u;
E[l].f = ;
E[l].v = v;
E[l].nxt = head[u];
head[u] = l++; E[l].u = v;
E[l].f = ;
E[l].v = u;
E[l].nxt = head[v];
head[v] = l++;
} void tarjan(int u, int fa) {
int v, k; low[u] = pre[u] = ++dfs_clock;
for (k=head[u]; k!=-; k=E[k].nxt) {
if (E[k].f)
continue;
E[k].f = E[k^].f = ;
v = E[k].v;
S[top++] = k;
if (!pre[v]) {
tarjan(v, u);
low[u] = min(low[u], low[v]);
if (low[v] >= pre[u]) {
iscut[u] = true;
++cnt[u];
bcc_cnt++;
while () {
int kk = S[--top];
bn[kk>>] = bcc_cnt;
bcc[E[kk].u].pb(bcc_cnt);
bcc[E[kk].v].pb(bcc_cnt);
if (kk == k)
break;
}
}
} else {
low[u] = min(low[u], pre[v]);
}
}
} void dfs(int u, int fa, int d) {
mark[u] = dfs_clock;
deep[u] = d;
V[++top] = u;
D[top] = d;
beg[u] = top; int v, k; for (k=head_[u]; k!=-; k=E_[k].nxt) {
v = E_[k].v;
if (v == fa)
continue;
dfs(v, u, d+);
V[++top] = u;
D[top] = d;
}
} void init_RMQ(int n) {
int i, j; for (i=; i<=n; ++i)
dp[][i] = i;
for (j=; (<<j)<=n; ++j)
for (i=; i+(<<j)-<=n; ++i)
if (D[dp[j-][i]] < D[dp[j-][i+(<<(j-))]])
dp[j][i] = dp[j-][i];
else
dp[j][i] = dp[j-][i+(<<(j-))];
} int RMQ(int l, int r) {
if (l > r)
swap(l, r); int k = ; while (<<(k+) <= r-l+)
++k; if (D[dp[k][l]] < D[dp[k][r-(<<k)+]])
return V[dp[k][l]];
else
return V[dp[k][r-(<<k)+]];
} void solve() {
int u, v, lca; rep(i, , n+) {
if (!pre[i]) {
tarjan(i, -);
if (cnt[i] <= )
iscut[i] = false;
}
} int cid = bcc_cnt; init_();
cid = bcc_cnt;
for (u=; u<=n; ++u) {
if (!iscut[u])
continue;
sort(all(bcc[u]));
cutn[++cid] = ;
addEdge_(cid, bcc[u][]);
int sz = SZ(bcc[u]);
rep(i, , sz) {
if (bcc[u][i] != bcc[u][i-]) {
addEdge_(cid, bcc[u][i]);
}
}
} top = ;
++dfs_clock;
rep(i, , cid+) {
if (mark[i] != dfs_clock)
dfs(i, , );
} init_RMQ(top); int q;
int ans; scanf("%d", &q);
while (q--) {
scanf("%d %d", &u, &v);
u = bn[u-];
v = bn[v-];
lca = RMQ(beg[u], beg[v]);
ans = (deep[u]+deep[v] - deep[lca]* + ) / ;
printf("%d\n", ans);
}
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int u, v; while (scanf("%d %d", &n, &m)!=EOF && (n||m)) {
init();
rep(i, , m) {
scanf("%d %d", &u, &v);
addEdge(u, v);
} solve();
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}
上一篇:Ruby的基本语法-数组


下一篇:java简易excel导入导出工具(封装POI)