HDU Traffic Real Time Query System

题目大意是:对于(n, m)的图,给定边a, b查询从a到b要经过的割点的最少数目。

先tarjan算法求双连通然后缩点,即对于每个割点将周围的每个双连通看成一个点与之相连。然后求解LCA即可,距离dis[u]表示从根出发到u的遍历过程中经过的割顶的数目,利用

tarjan离线算法, 最后答案是:dis[u] + dis[v] - 2*dis[findset(v)] + (findset(v) > bcc_cnt)。注意findset(v) > bcc_cnt表示当LCA(u,v) 为割顶时的判断,此时必须加1。

代码:

  1 #include <iostream>
  2 #include <sstream>
  3 #include <cstdio>
  4 #include <climits>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <string>
  8 #include <stack>
  9 #include <map>
 10 #include <cmath>
 11 #include <vector>
 12 #include <queue>
 13 #include <algorithm>
 14 #define esp 1e-6
 15 #define pi acos(-1.0)
 16 #define pb push_back
 17 #define lson l, m, rt<<1
 18 #define rson m+1, r, rt<<1|1
 19 #define mp(a, b) make_pair((a), (b))
 20 #define in  freopen("in.txt", "r", stdin);
 21 #define out freopen("out.txt", "w", stdout);
 22 #define print(a) printf("%d\n",(a));
 23 #define bug puts("********))))))");
 24 #define stop  system("pause");
 25 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
 26 #define inf 0x0f0f0f0f
 27 
 28 using namespace std;
 29 typedef long long  LL;
 30 typedef vector<int> VI;
 31 typedef pair<int, int> pii;
 32 typedef vector<pii> VII;
 33 typedef vector<pii, int> VIII;
 34 typedef VI:: iterator IT;
 35 #define eid first
 36 #define vtx second
 37 
 38 const int maxn = 10000 + 10000;
 39 const int maxm = 100000 + 10000;
 40 int pre[maxn], low[maxn], bccno[maxn], ebccno[maxm], iscut[maxn], vis[maxm], ans[maxn], pa[maxn], bcc_cnt, dfs_clock;
 41 VI g[maxn], bcc[maxn];
 42 VII adj[maxn], query[maxn];
 43 struct edge{
 44 int u, v;
 45 } ee[maxm];
 46 stack<int> S;
 47 
 48 int dfs(int u, int fa)
 49 {
 50     int lowu = pre[u] = ++dfs_clock;
 51     int child = 0;
 52     for(int i = 0; i < adj[u].size(); i++)
 53         {
 54             int v = adj[u][i].vtx;
 55             if(!pre[v])
 56             {
 57                 S.push(adj[u][i].eid);
 58                 child++;
 59                 vis[adj[u][i].eid] = 1;
 60                 int lowv = dfs(v, u);
 61                 lowu = min(lowu, lowv);
 62                 if(lowv >= pre[u])
 63                 {
 64                     iscut[u] = 1;
 65                     bcc_cnt++;
 66                     bcc[bcc_cnt].clear();
 67                     for(;;)
 68                     {
 69                         int e = S.top(); S.pop();
 70                         bcc[bcc_cnt].pb(e);
 71                         ebccno[e] = bcc_cnt;
 72                         bccno[ee[e].u] = bccno[ee[e].v] = bcc_cnt;
 73                         if(e == adj[u][i].eid)  break;
 74                     }
 75                 }
 76             }
 77             else if(pre[v] < pre[u])
 78             {
 79                   if(v != fa)
 80                   {
 81                      lowu = min(lowu, pre[v]);
 82                      S.push(adj[u][i].eid);
 83                      vis[adj[u][i].eid] = 1;
 84                   }
 85                   else {
 86                     if( !vis[adj[u][i].eid])
 87                     {
 88                       lowu = min(lowu, pre[v]);
 89                       S.push(adj[u][i].eid);
 90                       vis[adj[u][i].eid] = 1;
 91                     }
 92                   }
 93             }
 94         }
 95         if(fa < 0 && child == 1)
 96         {
 97             iscut[u] = 0;
 98         }
 99         return low[u] = lowu;
100 }
101 void find_bcc(int n)
102 {
103     memset(pre, 0, sizeof(pre));
104     memset(bccno, 0, sizeof(bccno));
105     memset(iscut, 0, sizeof(iscut));
106     memset(ebccno, 0, sizeof(ebccno));
107     memset(vis, 0, sizeof(vis));
108 
109     while(!S.empty()) S.pop();
110     dfs_clock = bcc_cnt = 0;
111     for(int i = 0; i < n ;i++)
112         if(!pre[i])
113         dfs(i, -1);
114 }
115 int flag[maxn];
116 int dis[maxn];
117 int vv[maxn];
118 int findset(int x)
119 {
120     return pa[x] == x ? x : pa[x] = findset(pa[x]);
121 }
122 void tarjan(int u, int d)
123 {
124     vv[u] = 1;
125     dis[u] = d;
126     pa[u] = u;
127     if(u > bcc_cnt)
128                dis[u]++;
129      for(int i = 0; i < query[u].size(); i++)
130      {
131          int v = query[u][i].first;
132          int id = query[u][i].second;
133          if(vis[v])
134             ans[id] = dis[u] + dis[v] - 2*dis[findset(v)] + (findset(v) > bcc_cnt);
135      }
136      for(int i = 0; i < g[u].size(); i++)
137      {
138          int v = g[u][i];
139          if(!vv[v])
140          {
141              tarjan(v, dis[u]);
142              pa[v] = u;
143          }
144      }
145 }
146 int main(void)
147 {
148     int n, m;
149     while(scanf("%d%d", &n, &m), n||m)
150     {
151         for(int i = 0; i < maxn; i++)
152             adj[i].clear(), g[i].clear(), query[i].clear();
153             memset(flag, -1, sizeof(flag));
154         for(int i = 1; i <= m; i++)
155         {
156             int u, v;
157             scanf("%d%d", &u, &v);
158             u--, v--;
159             adj[u].pb(mp(i, v));
160             adj[v].pb(mp(i, u));
161             ee[i].u = u, ee[i].v = v;
162         }
163         find_bcc(n);
164         int cut_cnt = 0;
165         for(int i = 0; i < n; i++)
166             if(iscut[i])
167         {
168             cut_cnt++;
169             int u = cut_cnt+bcc_cnt;
170             for(int k = 0; k < adj[i].size(); k++)
171             {
172                 int v = ebccno[adj[i][k].first];
173                 if(flag[v] != u )
174                 {
175                     flag[v] = u;
176                     g[v].pb(u);
177                     g[u].pb(v);
178                 }
179             }
180         }
181         int q;
182         for(int i = scanf("%d", &q); i <= q; i++)
183         {
184             int s, t;
185             scanf("%d%d", &s, &t);
186             s = ebccno[s], t = ebccno[t];
187             query[s].pb(mp(t, i));
188             query[t].pb(mp(s, i));
189         }
190         memset(vv, 0, sizeof(vv));
191         for(int i = 1; i <= bcc_cnt+cut_cnt; i++)
192             if(!vv[i])
193         tarjan(i, 0);
194         for(int i = 1; i <= q; i++)
195             printf("%d\n", ans[i]);
196     }
197     return 0;
198 }
View Code

 

这个也可用Sparse  Table(ST算法)结合RMQ求解LCA

下面是代码:

  1 #include <iostream>
  2 #include <sstream>
  3 #include <cstdio>
  4 #include <climits>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <string>
  8 #include <stack>
  9 #include <map>
 10 #include <cmath>
 11 #include <vector>
 12 #include <queue>
 13 #include <algorithm>
 14 #define esp 1e-6
 15 #define pi acos(-1.0)
 16 #define pb push_back
 17 #define lson l, m, rt<<1
 18 #define rson m+1, r, rt<<1|1
 19 #define mp(a, b) make_pair((a), (b))
 20 #define in  freopen("in.txt", "r", stdin);
 21 #define out freopen("out.txt", "w", stdout);
 22 #define print(a) printf("%d\n",(a));
 23 #define bug puts("********))))))");
 24 #define stop  system("pause");
 25 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
 26 #define inf 0x0f0f0f0f
 27 
 28 using namespace std;
 29 typedef long long  LL;
 30 typedef vector<int> VI;
 31 typedef pair<int, int> pii;
 32 typedef vector<pii> VII;
 33 typedef vector<pii, int> VIII;
 34 typedef VI:: iterator IT;
 35 #define eid first
 36 #define vtx second
 37 
 38 const int maxn = 10000 + 10000;
 39 const int maxm = 100000 + 10000;
 40 int pre[maxn], low[maxn], bccno[maxn], ebccno[maxm], iscut[maxn], vis[maxm], ans[maxn], pa[maxn], bcc_cnt, dfs_clock;
 41 int dep[maxn], E[maxn], R[maxn];
 42 int dp[maxn*2][30];
 43 VI g[maxn], bcc[maxn];
 44 VII adj[maxn], query[maxn];
 45 struct edge
 46 {
 47     int u, v;
 48 } ee[maxm];
 49 stack<int> S;
 50 int cnt;
 51 int dfs(int u, int fa)
 52 {
 53     int lowu = pre[u] = ++dfs_clock;
 54     int child = 0;
 55     for(int i = 0; i < adj[u].size(); i++)
 56     {
 57         int v = adj[u][i].vtx;
 58         if(!pre[v])
 59         {
 60             S.push(adj[u][i].eid);
 61             child++;
 62             vis[adj[u][i].eid] = 1;
 63             int lowv = dfs(v, u);
 64             lowu = min(lowu, lowv);
 65             if(lowv >= pre[u])
 66             {
 67                 iscut[u] = 1;
 68                 bcc_cnt++;
 69                 bcc[bcc_cnt].clear();
 70                 for(;;)
 71                 {
 72                     int e = S.top();
 73                     S.pop();
 74                     bcc[bcc_cnt].pb(e);
 75                     ebccno[e] = bcc_cnt;
 76                     bccno[ee[e].u] = bccno[ee[e].v] = bcc_cnt;
 77                     if(e == adj[u][i].eid)  break;
 78                 }
 79             }
 80         }
 81         else if(pre[v] < pre[u])
 82         {
 83             if(v != fa)
 84             {
 85                 lowu = min(lowu, pre[v]);
 86                 S.push(adj[u][i].eid);
 87                 vis[adj[u][i].eid] = 1;
 88             }
 89             else
 90             {
 91                 if( !vis[adj[u][i].eid])
 92                 {
 93                     lowu = min(lowu, pre[v]);
 94                     S.push(adj[u][i].eid);
 95                     vis[adj[u][i].eid] = 1;
 96                 }
 97             }
 98         }
 99     }
100     if(fa < 0 && child == 1)
101     {
102         iscut[u] = 0;
103     }
104     return low[u] = lowu;
105 }
106 void find_bcc(int n)
107 {
108     memset(pre, 0, sizeof(pre));
109     memset(bccno, 0, sizeof(bccno));
110     memset(iscut, 0, sizeof(iscut));
111     memset(ebccno, 0, sizeof(ebccno));
112     memset(vis, 0, sizeof(vis));
113 
114     while(!S.empty()) S.pop();
115     dfs_clock = bcc_cnt = 0;
116     for(int i = 0; i < n ; i++)
117         if(!pre[i])
118             dfs(i, -1);
119 }
120 int flag[maxn];
121 int dis[maxn];
122 int vv[maxn];
123 int findset(int x)
124 {
125     return pa[x] == x ? x : pa[x] = findset(pa[x]);
126 }
127 void ST(int u, int d, int sum)
128 {
129     vv[u] = 1;
130     R[u] = ++cnt;
131     dep[cnt] = d;
132     E[cnt] = u;
133     dis[u] = sum;
134     if(u > bcc_cnt)
135         dis[u]++;
136     for(int i = 0; i < g[u].size(); i++)
137     {
138         int v = g[u][i];
139         if(!vv[v])
140         {
141             ST(v, d+1, dis[u]);
142             E[++cnt] = u;
143             dep[cnt] = d;
144         }
145     }
146 }
147 void Init(void)
148 {
149     for(int i = 1; i <= cnt; i++)
150         dp[i][0] = i;
151     for(int j = 1; j <= (int)(log(cnt)/log(2.0)); j++)
152         for(int i = 1; i + (1<<j) - 1 <= cnt; i++)
153         {
154             if(dep[dp[i][j-1]] < dep[dp[i+(1<<(j-1))][j-1]])
155                 dp[i][j] = dp[i][j-1];
156             else dp[i][j] = dp[i + (1<<(j-1))][j-1];
157         }
158 }
159 int RMQ(int u, int v)
160 {
161     int k = (int)(log(v - u + 1)/log(2.0));
162     if(dep[dp[u][k]] < dep[dp[v - (1<<k) + 1][k]])
163         return dp[u][k];
164     return dp[v - (1<<k) + 1][k];
165 }
166 int main(void)
167 {
168     
169     int n, m;
170     while(scanf("%d%d", &n, &m), n||m)
171     {
172         for(int i = 0; i < maxn; i++)
173             adj[i].clear(), g[i].clear(), query[i].clear();
174         memset(flag, -1, sizeof(flag));
175         for(int i = 1; i <= m; i++)
176         {
177             int u, v;
178             scanf("%d%d", &u, &v);
179             u--, v--;
180             adj[u].pb(mp(i, v));
181             adj[v].pb(mp(i, u));
182             ee[i].u = u, ee[i].v = v;
183         }
184         find_bcc(n);
185         int cut_cnt = 0;
186         for(int i = 0; i < n; i++)
187             if(iscut[i])
188             {
189                 cut_cnt++;
190                 int u = cut_cnt+bcc_cnt;
191                 for(int k = 0; k < adj[i].size(); k++)
192                 {
193                     int v = ebccno[adj[i][k].first];
194                     if(flag[v] != u )
195                     {
196                         flag[v] = u;
197                         g[v].pb(u);
198                         g[u].pb(v);
199                     }
200                 }
201             }
202         memset(vv, 0, sizeof(vv));
203         cnt = 0;
204         for(int i = 1; i <= bcc_cnt+cut_cnt; i++)
205             if(!vv[i])
206                 ST(i, 0, 0);
207         int q;
208         Init();//记得初始化啊  。。。。。。。。
209         for(int i = scanf("%d", &q); i <= q; i++)
210         {
211             int s, t;
212             scanf("%d%d", &s, &t);
213             s = ebccno[s], t = ebccno[t];
214             int ss , tt;
215             ss = min(R[s], R[t]);
216             tt = max(R[s], R[t]);
217             int lca = RMQ(ss, tt);
218             lca = E[lca];
219             int ans = dis[s] + dis[t] - 2 * dis[lca] + (lca > bcc_cnt);
220             printf("%d\n", ans);
221         }
222     }
223     return 0;
224 }
View Code

 

两者时间上差不多,而且ST算法需要初始化,更容易出错

posted on 2013-10-12 23:13  rootial  阅读(354)  评论(0编辑  收藏  举报

导航