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。
代码:
- #include <iostream>
- #include <sstream>
- #include <cstdio>
- #include <climits>
- #include <cstring>
- #include <cstdlib>
- #include <string>
- #include <stack>
- #include <map>
- #include <cmath>
- #include <vector>
- #include <queue>
- #include <algorithm>
- #define esp 1e-6
- #define pi acos(-1.0)
- #define pb push_back
- #define lson l, m, rt<<1
- #define rson m+1, r, rt<<1|1
- #define mp(a, b) make_pair((a), (b))
- #define in freopen("in.txt", "r", stdin);
- #define out freopen("out.txt", "w", stdout);
- #define print(a) printf("%d\n",(a));
- #define bug puts("********))))))");
- #define stop system("pause");
- #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
- #define inf 0x0f0f0f0f
- using namespace std;
- typedef long long LL;
- typedef vector<int> VI;
- typedef pair<int, int> pii;
- typedef vector<pii> VII;
- typedef vector<pii, int> VIII;
- typedef VI:: iterator IT;
- #define eid first
- #define vtx second
- const int maxn = + ;
- const int maxm = + ;
- int pre[maxn], low[maxn], bccno[maxn], ebccno[maxm], iscut[maxn], vis[maxm], ans[maxn], pa[maxn], bcc_cnt, dfs_clock;
- VI g[maxn], bcc[maxn];
- VII adj[maxn], query[maxn];
- struct edge{
- int u, v;
- } ee[maxm];
- stack<int> S;
- int dfs(int u, int fa)
- {
- int lowu = pre[u] = ++dfs_clock;
- int child = ;
- for(int i = ; i < adj[u].size(); i++)
- {
- int v = adj[u][i].vtx;
- if(!pre[v])
- {
- S.push(adj[u][i].eid);
- child++;
- vis[adj[u][i].eid] = ;
- int lowv = dfs(v, u);
- lowu = min(lowu, lowv);
- if(lowv >= pre[u])
- {
- iscut[u] = ;
- bcc_cnt++;
- bcc[bcc_cnt].clear();
- for(;;)
- {
- int e = S.top(); S.pop();
- bcc[bcc_cnt].pb(e);
- ebccno[e] = bcc_cnt;
- bccno[ee[e].u] = bccno[ee[e].v] = bcc_cnt;
- if(e == adj[u][i].eid) break;
- }
- }
- }
- else if(pre[v] < pre[u])
- {
- if(v != fa)
- {
- lowu = min(lowu, pre[v]);
- S.push(adj[u][i].eid);
- vis[adj[u][i].eid] = ;
- }
- else {
- if( !vis[adj[u][i].eid])
- {
- lowu = min(lowu, pre[v]);
- S.push(adj[u][i].eid);
- vis[adj[u][i].eid] = ;
- }
- }
- }
- }
- if(fa < && child == )
- {
- iscut[u] = ;
- }
- return low[u] = lowu;
- }
- void find_bcc(int n)
- {
- memset(pre, , sizeof(pre));
- memset(bccno, , sizeof(bccno));
- memset(iscut, , sizeof(iscut));
- memset(ebccno, , sizeof(ebccno));
- memset(vis, , sizeof(vis));
- while(!S.empty()) S.pop();
- dfs_clock = bcc_cnt = ;
- for(int i = ; i < n ;i++)
- if(!pre[i])
- dfs(i, -);
- }
- int flag[maxn];
- int dis[maxn];
- int vv[maxn];
- int findset(int x)
- {
- return pa[x] == x ? x : pa[x] = findset(pa[x]);
- }
- void tarjan(int u, int d)
- {
- vv[u] = ;
- dis[u] = d;
- pa[u] = u;
- if(u > bcc_cnt)
- dis[u]++;
- for(int i = ; i < query[u].size(); i++)
- {
- int v = query[u][i].first;
- int id = query[u][i].second;
- if(vis[v])
- ans[id] = dis[u] + dis[v] - *dis[findset(v)] + (findset(v) > bcc_cnt);
- }
- for(int i = ; i < g[u].size(); i++)
- {
- int v = g[u][i];
- if(!vv[v])
- {
- tarjan(v, dis[u]);
- pa[v] = u;
- }
- }
- }
- int main(void)
- {
- int n, m;
- while(scanf("%d%d", &n, &m), n||m)
- {
- for(int i = ; i < maxn; i++)
- adj[i].clear(), g[i].clear(), query[i].clear();
- memset(flag, -, sizeof(flag));
- for(int i = ; i <= m; i++)
- {
- int u, v;
- scanf("%d%d", &u, &v);
- u--, v--;
- adj[u].pb(mp(i, v));
- adj[v].pb(mp(i, u));
- ee[i].u = u, ee[i].v = v;
- }
- find_bcc(n);
- int cut_cnt = ;
- for(int i = ; i < n; i++)
- if(iscut[i])
- {
- cut_cnt++;
- int u = cut_cnt+bcc_cnt;
- for(int k = ; k < adj[i].size(); k++)
- {
- int v = ebccno[adj[i][k].first];
- if(flag[v] != u )
- {
- flag[v] = u;
- g[v].pb(u);
- g[u].pb(v);
- }
- }
- }
- int q;
- for(int i = scanf("%d", &q); i <= q; i++)
- {
- int s, t;
- scanf("%d%d", &s, &t);
- s = ebccno[s], t = ebccno[t];
- query[s].pb(mp(t, i));
- query[t].pb(mp(s, i));
- }
- memset(vv, , sizeof(vv));
- for(int i = ; i <= bcc_cnt+cut_cnt; i++)
- if(!vv[i])
- tarjan(i, );
- for(int i = ; i <= q; i++)
- printf("%d\n", ans[i]);
- }
- return ;
- }
这个也可用Sparse Table(ST算法)结合RMQ求解LCA
下面是代码:
- #include <iostream>
- #include <sstream>
- #include <cstdio>
- #include <climits>
- #include <cstring>
- #include <cstdlib>
- #include <string>
- #include <stack>
- #include <map>
- #include <cmath>
- #include <vector>
- #include <queue>
- #include <algorithm>
- #define esp 1e-6
- #define pi acos(-1.0)
- #define pb push_back
- #define lson l, m, rt<<1
- #define rson m+1, r, rt<<1|1
- #define mp(a, b) make_pair((a), (b))
- #define in freopen("in.txt", "r", stdin);
- #define out freopen("out.txt", "w", stdout);
- #define print(a) printf("%d\n",(a));
- #define bug puts("********))))))");
- #define stop system("pause");
- #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
- #define inf 0x0f0f0f0f
- using namespace std;
- typedef long long LL;
- typedef vector<int> VI;
- typedef pair<int, int> pii;
- typedef vector<pii> VII;
- typedef vector<pii, int> VIII;
- typedef VI:: iterator IT;
- #define eid first
- #define vtx second
- const int maxn = + ;
- const int maxm = + ;
- int pre[maxn], low[maxn], bccno[maxn], ebccno[maxm], iscut[maxn], vis[maxm], ans[maxn], pa[maxn], bcc_cnt, dfs_clock;
- int dep[maxn], E[maxn], R[maxn];
- int dp[maxn*][];
- VI g[maxn], bcc[maxn];
- VII adj[maxn], query[maxn];
- struct edge
- {
- int u, v;
- } ee[maxm];
- stack<int> S;
- int cnt;
- int dfs(int u, int fa)
- {
- int lowu = pre[u] = ++dfs_clock;
- int child = ;
- for(int i = ; i < adj[u].size(); i++)
- {
- int v = adj[u][i].vtx;
- if(!pre[v])
- {
- S.push(adj[u][i].eid);
- child++;
- vis[adj[u][i].eid] = ;
- int lowv = dfs(v, u);
- lowu = min(lowu, lowv);
- if(lowv >= pre[u])
- {
- iscut[u] = ;
- bcc_cnt++;
- bcc[bcc_cnt].clear();
- for(;;)
- {
- int e = S.top();
- S.pop();
- bcc[bcc_cnt].pb(e);
- ebccno[e] = bcc_cnt;
- bccno[ee[e].u] = bccno[ee[e].v] = bcc_cnt;
- if(e == adj[u][i].eid) break;
- }
- }
- }
- else if(pre[v] < pre[u])
- {
- if(v != fa)
- {
- lowu = min(lowu, pre[v]);
- S.push(adj[u][i].eid);
- vis[adj[u][i].eid] = ;
- }
- else
- {
- if( !vis[adj[u][i].eid])
- {
- lowu = min(lowu, pre[v]);
- S.push(adj[u][i].eid);
- vis[adj[u][i].eid] = ;
- }
- }
- }
- }
- if(fa < && child == )
- {
- iscut[u] = ;
- }
- return low[u] = lowu;
- }
- void find_bcc(int n)
- {
- memset(pre, , sizeof(pre));
- memset(bccno, , sizeof(bccno));
- memset(iscut, , sizeof(iscut));
- memset(ebccno, , sizeof(ebccno));
- memset(vis, , sizeof(vis));
- while(!S.empty()) S.pop();
- dfs_clock = bcc_cnt = ;
- for(int i = ; i < n ; i++)
- if(!pre[i])
- dfs(i, -);
- }
- int flag[maxn];
- int dis[maxn];
- int vv[maxn];
- int findset(int x)
- {
- return pa[x] == x ? x : pa[x] = findset(pa[x]);
- }
- void ST(int u, int d, int sum)
- {
- vv[u] = ;
- R[u] = ++cnt;
- dep[cnt] = d;
- E[cnt] = u;
- dis[u] = sum;
- if(u > bcc_cnt)
- dis[u]++;
- for(int i = ; i < g[u].size(); i++)
- {
- int v = g[u][i];
- if(!vv[v])
- {
- ST(v, d+, dis[u]);
- E[++cnt] = u;
- dep[cnt] = d;
- }
- }
- }
- void Init(void)
- {
- for(int i = ; i <= cnt; i++)
- dp[i][] = i;
- for(int j = ; j <= (int)(log(cnt)/log(2.0)); j++)
- for(int i = ; i + (<<j) - <= cnt; i++)
- {
- if(dep[dp[i][j-]] < dep[dp[i+(<<(j-))][j-]])
- dp[i][j] = dp[i][j-];
- else dp[i][j] = dp[i + (<<(j-))][j-];
- }
- }
- int RMQ(int u, int v)
- {
- int k = (int)(log(v - u + )/log(2.0));
- if(dep[dp[u][k]] < dep[dp[v - (<<k) + ][k]])
- return dp[u][k];
- return dp[v - (<<k) + ][k];
- }
- int main(void)
- {
- int n, m;
- while(scanf("%d%d", &n, &m), n||m)
- {
- for(int i = ; i < maxn; i++)
- adj[i].clear(), g[i].clear(), query[i].clear();
- memset(flag, -, sizeof(flag));
- for(int i = ; i <= m; i++)
- {
- int u, v;
- scanf("%d%d", &u, &v);
- u--, v--;
- adj[u].pb(mp(i, v));
- adj[v].pb(mp(i, u));
- ee[i].u = u, ee[i].v = v;
- }
- find_bcc(n);
- int cut_cnt = ;
- for(int i = ; i < n; i++)
- if(iscut[i])
- {
- cut_cnt++;
- int u = cut_cnt+bcc_cnt;
- for(int k = ; k < adj[i].size(); k++)
- {
- int v = ebccno[adj[i][k].first];
- if(flag[v] != u )
- {
- flag[v] = u;
- g[v].pb(u);
- g[u].pb(v);
- }
- }
- }
- memset(vv, , sizeof(vv));
- cnt = ;
- for(int i = ; i <= bcc_cnt+cut_cnt; i++)
- if(!vv[i])
- ST(i, , );
- int q;
- Init();//记得初始化啊 。。。。。。。。
- for(int i = scanf("%d", &q); i <= q; i++)
- {
- int s, t;
- scanf("%d%d", &s, &t);
- s = ebccno[s], t = ebccno[t];
- int ss , tt;
- ss = min(R[s], R[t]);
- tt = max(R[s], R[t]);
- int lca = RMQ(ss, tt);
- lca = E[lca];
- int ans = dis[s] + dis[t] - * dis[lca] + (lca > bcc_cnt);
- printf("%d\n", ans);
- }
- }
- return ;
- }
两者时间上差不多,而且ST算法需要初始化,更容易出错
HDU Traffic Real Time Query System的更多相关文章
- HDU 3686 Traffic Real Time Query System (图论)
HDU 3686 Traffic Real Time Query System 题目大意 给一个N个点M条边的无向图,然后有Q个询问X,Y,问第X边到第Y边必需要经过的点有多少个. solution ...
- CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System
逃不掉的路 CH Round #24 - 三体杯 Round #1 题目描述 现代社会,路是必不可少的.任意两个城镇都有路相连,而且往往不止一条.但有些路连年被各种XXOO,走着很不爽.按理说条条大路 ...
- HDU 3686 Traffic Real Time Query System(双连通分量缩点+LCA)(2010 Asia Hangzhou Regional Contest)
Problem Description City C is really a nightmare of all drivers for its traffic jams. To solve the t ...
- HDU3686 Traffic Real Time Query System 题解
题目 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, t ...
- Traffic Real Time Query System 圆方树+LCA
题目描述 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, ...
- hdu 3686 Traffic Real Time Query System 点双两通分量 + LCA。这题有重边!!!
http://acm.hdu.edu.cn/showproblem.php?pid=3686 我要把这题记录下来. 一直wa. 自己生成数据都是AC的.现在还是wa.留坑. 我感觉我现在倒下去床上就能 ...
- Traffic Real Time Query System HDU - 3686
https://vjudge.net/problem/HDU-3686 点双啊,就是在求割顶的时候,另外用一个栈来存一些边 在遍历u点出发的边时,遇到树边或反向边(u,v)就把此边加入栈(可能要记一下 ...
- HDU 3686 Traffic Real Time Query System(点双连通)
题意 给定一张 \(n\) 个点 \(m\) 条边的无向图,\(q\) 次询问,每次询问两边之间的必经之点个数. 思路 求两点之间必经之边的个数用的是边双缩点,再求树上距离.而对比边双和点双之 ...
- UVALive-4839 HDU-3686 Traffic Real Time Query System 题解
题目大意: 有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个. 思路: 先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求 ...
随机推荐
- MySQL flush privileges 명령어
INSERT나 UPDATE, DELETE문을 이용해서 MySQL의 사용자를 추가,삭제하거나, 사용자 권한 등을 변경하였을 때, MySQL에 변경사항을 적용하기 위해서 사용하는 명령 ...
- 【MINA】序列化和反序列化我们要考虑的问题
概念 序列化:将java对象转换为字节序列的过程叫做序列化 反序列化:将字节对象转换为java对象的过程叫做反序列化 要解决的问题 1.序列化时间 2.反序列化时间 3.bytes大小 4.操作方便 ...
- 本地缓存下载文件,download的二次封装
来源:http://ask.dcloud.net.cn/article/524 源码下载链接 说明: (1)由于平时项目中大量用到了附件下载等功能,所以就花了一个时间,把plus的downlaod进行 ...
- SQLSERVER2000以上 Ad Hoc Distributed Queries的启用与关闭
SQLSERVER2000以上的版本在查询分析器中查询ACCESS数据时提示:“ 訊息 15281,層級 16,狀態 1,行 1SQL Server 已封鎖元件 'Ad Hoc Distributed ...
- CS0016: 未能写入输出文件“c:\windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\data\34aae060\b7daa87d\App_Web_addadvice.aspx.cdcab7d2.ekhlcbjd.dll”--“目录名无效。 ”
产生原因: 应用程序运行时产生的临时文件需要存放到c:"windows"temp 文件夹下 而运行基于microsoft .net framework 框架下的应用程序 需要对te ...
- ASP.NET Web Service如何工作(1)
ASP.NET Web Service如何工作(1) [日期:2003-06-26] 来源:CSDN 作者:sunnyzhao(翻译) [字体:大 中 小] Summary ASP.NET Web ...
- 10_控制线程_线程让步yield
[线程让步yield()方法] yield()方法可以让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程从运行状态转入就绪状态. 只是让当前的线程暂停一下,让系统的线程调度器重新调度一次. ...
- KMP入门(周期)
Description Given two strings a and b we define a*b to be their concatenation. For example, if a = & ...
- Wix: Show conditional message box
For example: Scenario: Show message box only during installation and MYPROPERTY has to be equal to & ...
- 安装kali之后
更新源(以下设置均基于这些源) #vi /etc/apt/sources.list 把这些源加进去 ############################ debian wheezy ####### ...