题目大意是:对于(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的更多相关文章

  1. HDU 3686 Traffic Real Time Query System (图论)

    HDU 3686 Traffic Real Time Query System 题目大意 给一个N个点M条边的无向图,然后有Q个询问X,Y,问第X边到第Y边必需要经过的点有多少个. solution ...

  2. CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System

    逃不掉的路 CH Round #24 - 三体杯 Round #1 题目描述 现代社会,路是必不可少的.任意两个城镇都有路相连,而且往往不止一条.但有些路连年被各种XXOO,走着很不爽.按理说条条大路 ...

  3. 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 ...

  4. 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 ...

  5. Traffic Real Time Query System 圆方树+LCA

    题目描述 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, ...

  6. hdu 3686 Traffic Real Time Query System 点双两通分量 + LCA。这题有重边!!!

    http://acm.hdu.edu.cn/showproblem.php?pid=3686 我要把这题记录下来. 一直wa. 自己生成数据都是AC的.现在还是wa.留坑. 我感觉我现在倒下去床上就能 ...

  7. Traffic Real Time Query System HDU - 3686

    https://vjudge.net/problem/HDU-3686 点双啊,就是在求割顶的时候,另外用一个栈来存一些边 在遍历u点出发的边时,遇到树边或反向边(u,v)就把此边加入栈(可能要记一下 ...

  8. HDU 3686 Traffic Real Time Query System(点双连通)

    题意 ​ 给定一张 \(n\) 个点 \(m\) 条边的无向图,\(q\) 次询问,每次询问两边之间的必经之点个数. 思路 ​ 求两点之间必经之边的个数用的是边双缩点,再求树上距离.而对比边双和点双之 ...

  9. UVALive-4839 HDU-3686 Traffic Real Time Query System 题解

    题目大意: 有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个. 思路: 先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求 ...

随机推荐

  1. MySQL - 启停服务

    Windows 环境 命令行方式 启动 MySQL 服务: net start mysql停止 MySQL 服务: net stop mysql 注:需要以管理员身份启动 cmd 后再执行上述命令. ...

  2. 在C#中创建类型

    重载构造函数: using System; public class Wine { public decimal Price; public int Year; public Wine (decima ...

  3. Android 内存溢出管理与测试

    今天发现正在做的项目,时不时的会报错:dalvikvm heap out of memory on a 7458832-byte allocation (堆分配的内存溢出) 为什么会内存溢出呢?我以前 ...

  4. MongoDB的主从复制和副本集

    mongoDB的两个特性主从复制和副本集,实现了数据的同步备份 一.主从复制 主从复制是一个简单的数据库同步备份的集群技术.例如主服务器宕机了,可以直接使用从服务器,主服务器恢复后在进行同步,保证了业 ...

  5. SQL Server(基本) 关键字的使用 一

    一, 基础关键字 -- 使用介绍 1,select 的使用(select 结果集) SELECT 列名称 FROM 表名称 以及: (*)是选取所有列的快捷方式. SELECT * FROM 表名称 ...

  6. Asp.net网页中禁止使用剪切、复制、粘贴的方法

    工欲善其事,必先利其器 在asp.net开发的网页中,有时候需要禁止用户粘贴复制密码,禁止用户copy文章直接粘贴到文本框中.采取的方法是直接在限制控件的地方写上禁止粘贴文本的代码.但是这样不是很方便 ...

  7. iOS网络编程总结

    好长时间没有进行更行了,最近学到AFNetworking框架,在学习完成之后做出一个总结 1.第三方网络的框架 AFNEtworking使用简单,对最新的iOS特性都有很好的支持,对NSURL进行了封 ...

  8. hybird app

    Hybrid App 是混合模式应用的简称,兼具 Native App 和 Web App 两种模式应用的优势,开发成本低,拥有 Web 技术跨平台特性.目前大家所知道的基于中间件的移动开发框架都是采 ...

  9. C#对XML、JSON等格式的解析

    C#对XML.JSON等格式的解析 一.C#对XML格式数据的解析 1.用XMLDocument来解析 XmlDocument xmlDocument = new XmlDocument(); xml ...

  10. MVC控制器给View返回实体

    前言 这几天把vs12更新到了vs12 5了,因为发现我之前装的12有问题,没有mvc,之后就从itellyou上下载了12的update5更新了一下.说实话,从开发到现在,自己只是平时自己玩用mvc ...