【HDOJ】3686 Traffic Real Time Query System

这题做了几个小时,基本思路肯定是求两点路径中的割点数目,思路是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-12-28 21:32:44

【HDOJ】3686 Traffic Real Time Query System的相关文章

hdu 3686 Traffic Real Time Query System 点双两通分量 + LCA

http://acm.hdu.edu.cn/showproblem.php?pid=3686 我要把这题记录下来. 一直wa. 自己生成数据都是AC的.现在还是wa.留坑. 我感觉我现在倒下去床上就能睡着了. 不知道是我的LCA错了,还是tarjan #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #incl

UVALive 4839 HDU 3686 Traffic Real Time Query System

题意: 寻找图中从一条边到另一条边的路径上必须经过的点的个数 思路: 首先必经过的一定是割点  因此可以先做点双连通然后缩点  缩完点后形成了树  而且树上的路径是满足"非割点-割点-非割点-割点--"这样的模式的  路径u->v只需要求出他们的lca  则答案可以通过(dis[u]+dis[v]-dis[lca]*2)/2算出 注意: 这题缩点是通过边来进行的  因为这样可以使每条边都在一个连通块中 -- by wuyiqi PS: 代码中缩点的部分借鉴了 Sd.无心插柳 的代

【HDOJ】2795 Billboard

线段树.注意h范围(小于等于n). 1 #include <stdio.h> 2 #include <string.h> 3 4 #define MAXN 200005 5 #define lson l, mid, rt<<1 6 #define rson mid+1, r, rt<<1|1 7 #define mymax(x, y) (x>y) ? x:y 8 9 int nums[MAXN<<2]; 10 int h, w; 11 12

【HDOJ】2492 Ping pong

线段树+离散化. 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 5 #define MAXN 20005 6 #define lson l, mid, rt<<1 7 #define rson mid+1, r, rt<<1|1 8 9 int buf[MAXN], bk[MAXN]; 10 int sum[MAXN<<2], n; 11 12 int

【HDOJ】1823 Luck and Love

二维线段树.wa了几次,不存在输出-1,而不再是一位小数. 1 #include <cstdio> 2 #include <cstring> 3 4 #define MAXN 105 5 #define MAXM 1005 6 #define lson l, mid, rt<<1 7 #define rson mid+1, r, rt<<1|1 8 9 double sons[MAXN<<2][MAXM<<2]; 10 11 inli

【HDOJ】1754 I Hate It

线段树. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 #define mymax(a, b) (a>b) ? a:b 7 8 const int maxn = 200005; 9 10 int nums[maxn<<2]; 11 12 void PushUP(int rt) { 13 nums[rt] = mymax(

【HDOJ】1892 See you~

wa了十次,原来变量名写错.二维树状数组. 1 #include <cstdio> 2 #include <cstring> 3 4 #define MAXN 1002 5 6 int nums[MAXN][MAXN]; 7 8 void swap(int *x, int *y) { 9 int tmp; 10 tmp = *x; 11 *x = *y; 12 *y = tmp; 13 } 14 15 int lowbit(int i) { 16 return i & (-

【HDOJ】4956 Poor Hanamichi

基本数学题一道,看错位数,当成大数减做了,而且还把方向看反了.所求为最接近l的值. 1 #include <cstdio> 2 3 int f(__int64 x) { 4 int i, sum; 5 6 i = sum = 0; 7 while (x) { 8 if (i & 1) 9 sum -= x%10; 10 else 11 sum += x%10; 12 ++i; 13 x/=10; 14 } 15 return sum; 16 } 17 18 int main() { 1

【HDOJ】1099 Lottery

题意超难懂,实则一道概率论的题目.求P(n).P(n) = n*(1+1/2+1/3+1/4+...+1/n).结果如果可以除尽则表示为整数,否则表示为假分数. 1 #include <cstdio> 2 #include <cstring> 3 4 #define MAXN 25 5 6 __int64 buf[MAXN]; 7 8 __int64 gcd(__int64 a, __int64 b) { 9 if (b == 0) return a; 10 else return