这题做了几个小时,基本思路肯定是求两点路径中的割点数目,思路是tarjan缩点,然后以割点和连通块作为新节点见图。转化为lca求解。
结合点——双连通分量与LCA。
1 /* 3686 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <algorithm> 12 #include <cstdio> 13 #include <cmath> 14 #include <ctime> 15 #include <cstring> 16 #include <climits> 17 #include <cctype> 18 #include <cassert> 19 #include <functional> 20 #include <iterator> 21 #include <iomanip> 22 using namespace std; 23 //#pragma comment(linker,"/STACK:102400000,1024000") 24 25 #define sti set<int> 26 #define stpii set<pair<int, int> > 27 #define mpii map<int,int> 28 #define vi vector<int> 29 #define pii pair<int,int> 30 #define vpii vector<pair<int,int> > 31 #define rep(i, a, n) for (int i=a;i<n;++i) 32 #define per(i, a, n) for (int i=n-1;i>=a;--i) 33 #define clr clear 34 #define pb push_back 35 #define mp make_pair 36 #define fir first 37 #define sec second 38 #define all(x) (x).begin(),(x).end() 39 #define SZ(x) ((int)(x).size()) 40 #define lson l, mid, rt<<1 41 #define rson mid+1, r, rt<<1|1 42 43 typedef struct { 44 int u, v, f, nxt; 45 } edge_t; 46 47 typedef struct { 48 int v, nxt; 49 } edge; 50 51 const int maxv = 10005; 52 const int maxe = 200005; 53 int head[maxv], l, top; 54 int pre[maxv], low[maxv]; 55 bool iscut[maxv]; 56 int cnt[maxv], dfs_clock, bcc_cnt; 57 int bn[maxe]; 58 int S[maxe]; 59 vi bcc[maxv]; 60 edge_t E[maxe]; 61 int n, m; 62 63 const int maxvv = maxv * 2; 64 int mark[maxvv]; 65 int head_[maxvv], l_; 66 int cutn[maxvv]; 67 edge E_[maxe]; 68 69 int deep[maxvv], beg[maxvv]; 70 int V[maxvv<<1], D[maxvv<<1]; 71 72 int dp[16][maxvv<<1]; 73 74 void init_() { 75 memset(head_, -1, sizeof(head_)); 76 memset(mark, 0, sizeof(mark)); 77 l_ = 0; 78 } 79 80 void addEdge_(int u, int v) { 81 E_[l_].v = v; 82 E_[l_].nxt = head_[u]; 83 head_[u] = l_++; 84 85 E_[l_].v = u; 86 E_[l_].nxt = head_[v]; 87 head_[v] = l_++; 88 } 89 90 void init() { 91 l = dfs_clock = bcc_cnt = top = 0; 92 memset(head, -1, sizeof(head)); 93 memset(iscut, false, sizeof(iscut)); 94 memset(cnt, 0, sizeof(cnt)); 95 memset(cutn, 0, sizeof(cutn)); 96 memset(pre, 0, sizeof(pre)); 97 rep(i, 1, n+1) 98 bcc[i].clr(); 99 } 100 101 void addEdge(int u, int v) { 102 E[l].u = u; 103 E[l].f = 0; 104 E[l].v = v; 105 E[l].nxt = head[u]; 106 head[u] = l++; 107 108 E[l].u = v; 109 E[l].f = 0; 110 E[l].v = u; 111 E[l].nxt = head[v]; 112 head[v] = l++; 113 } 114 115 void tarjan(int u, int fa) { 116 int v, k; 117 118 low[u] = pre[u] = ++dfs_clock; 119 for (k=head[u]; k!=-1; k=E[k].nxt) { 120 if (E[k].f) 121 continue; 122 E[k].f = E[k^1].f = 1; 123 v = E[k].v; 124 S[top++] = k; 125 if (!pre[v]) { 126 tarjan(v, u); 127 low[u] = min(low[u], low[v]); 128 if (low[v] >= pre[u]) { 129 iscut[u] = true; 130 ++cnt[u]; 131 bcc_cnt++; 132 while (1) { 133 int kk = S[--top]; 134 bn[kk>>1] = bcc_cnt; 135 bcc[E[kk].u].pb(bcc_cnt); 136 bcc[E[kk].v].pb(bcc_cnt); 137 if (kk == k) 138 break; 139 } 140 } 141 } else { 142 low[u] = min(low[u], pre[v]); 143 } 144 } 145 } 146 147 void dfs(int u, int fa, int d) { 148 mark[u] = dfs_clock; 149 deep[u] = d; 150 V[++top] = u; 151 D[top] = d; 152 beg[u] = top; 153 154 int v, k; 155 156 for (k=head_[u]; k!=-1; k=E_[k].nxt) { 157 v = E_[k].v; 158 if (v == fa) 159 continue; 160 dfs(v, u, d+1); 161 V[++top] = u; 162 D[top] = d; 163 } 164 } 165 166 void init_RMQ(int n) { 167 int i, j; 168 169 for (i=1; i<=n; ++i) 170 dp[0][i] = i; 171 for (j=1; (1<<j)<=n; ++j) 172 for (i=1; i+(1<<j)-1<=n; ++i) 173 if (D[dp[j-1][i]] < D[dp[j-1][i+(1<<(j-1))]]) 174 dp[j][i] = dp[j-1][i]; 175 else 176 dp[j][i] = dp[j-1][i+(1<<(j-1))]; 177 } 178 179 int RMQ(int l, int r) { 180 if (l > r) 181 swap(l, r); 182 183 int k = 0; 184 185 while (1<<(k+1) <= r-l+1) 186 ++k; 187 188 if (D[dp[k][l]] < D[dp[k][r-(1<<k)+1]]) 189 return V[dp[k][l]]; 190 else 191 return V[dp[k][r-(1<<k)+1]]; 192 } 193 194 void solve() { 195 int u, v, lca; 196 197 rep(i, 1, n+1) { 198 if (!pre[i]) { 199 tarjan(i, -1); 200 if (cnt[i] <= 1) 201 iscut[i] = false; 202 } 203 } 204 205 int cid = bcc_cnt; 206 207 init_(); 208 cid = bcc_cnt; 209 for (u=1; u<=n; ++u) { 210 if (!iscut[u]) 211 continue; 212 sort(all(bcc[u])); 213 cutn[++cid] = 1; 214 addEdge_(cid, bcc[u][0]); 215 int sz = SZ(bcc[u]); 216 rep(i, 1, sz) { 217 if (bcc[u][i] != bcc[u][i-1]) { 218 addEdge_(cid, bcc[u][i]); 219 } 220 } 221 } 222 223 top = 0; 224 ++dfs_clock; 225 rep(i, 1, cid+1) { 226 if (mark[i] != dfs_clock) 227 dfs(i, 0, 0); 228 } 229 230 init_RMQ(top); 231 232 int q; 233 int ans; 234 235 scanf("%d", &q); 236 while (q--) { 237 scanf("%d %d", &u, &v); 238 u = bn[u-1]; 239 v = bn[v-1]; 240 lca = RMQ(beg[u], beg[v]); 241 ans = (deep[u]+deep[v] - deep[lca]*2 + 1) / 2; 242 printf("%d\n", ans); 243 } 244 } 245 246 int main() { 247 ios::sync_with_stdio(false); 248 #ifndef ONLINE_JUDGE 249 freopen("data.in", "r", stdin); 250 freopen("data.out", "w", stdout); 251 #endif 252 253 int u, v; 254 255 while (scanf("%d %d", &n, &m)!=EOF && (n||m)) { 256 init(); 257 rep(i, 0, m) { 258 scanf("%d %d", &u, &v); 259 addEdge(u, v); 260 } 261 262 solve(); 263 } 264 265 #ifndef ONLINE_JUDGE 266 printf("time = %d.\n", (int)clock()); 267 #endif 268 269 return 0; 270 }
时间: 2024-10-25 14:55:59