hdu 4547 lca-tarjan离线算法
来源:互联网 发布:网页页面设计软件 编辑:程序博客网 时间:2024/04/24 22:04
题意:
Problem Description
在Windows下我们可以通过cmd运行DOS的部分功能,其中CD是一条很有意思的命令,通过CD操作,我们可以改变当前目录。
这里我们简化一下问题,假设只有一个根目录,CD操作也只有两种方式:
1. CD 当前目录名\...\目标目录名 (中间可以包含若干目录,保证目标目录通过绝对路径可达)
2. CD .. (返回当前目录的上级目录)
现在给出当前目录和一个目标目录,请问最少需要几次CD操作才能将当前目录变成目标目录?
这里我们简化一下问题,假设只有一个根目录,CD操作也只有两种方式:
1. CD 当前目录名\...\目标目录名 (中间可以包含若干目录,保证目标目录通过绝对路径可达)
2. CD .. (返回当前目录的上级目录)
现在给出当前目录和一个目标目录,请问最少需要几次CD操作才能将当前目录变成目标目录?
Input
输入数据第一行包含一个整数T(T<=20),表示样例个数;
每个样例首先一行是两个整数N和M(1<=N,M<=100000),表示有N个目录和M个询问;
接下来N-1行每行两个目录名A B(目录名是只含有数字或字母,长度小于40的字符串),表示A的父目录是B。
最后M行每行两个目录名A B,表示询问将当前目录从A变成B最少要多少次CD操作。
数据保证合法,一定存在一个根目录,每个目录都能从根目录访问到。
每个样例首先一行是两个整数N和M(1<=N,M<=100000),表示有N个目录和M个询问;
接下来N-1行每行两个目录名A B(目录名是只含有数字或字母,长度小于40的字符串),表示A的父目录是B。
最后M行每行两个目录名A B,表示询问将当前目录从A变成B最少要多少次CD操作。
数据保证合法,一定存在一个根目录,每个目录都能从根目录访问到。
Output
请输出每次询问的结果,每个查询的输出占一行。
Sample Input
23 1B AC AB C3 2B AC BA CC A
Sample Output
212
解析:
错了一个下午,用各种姿势wa。
不知道为什么一定要按照问题的id去排最后的ans。
难道输出就不是有序的吗。。。
就算是这里的问题,st在线算法还是wa。。。无言以对,不知道什么数据卡了。
代码:
换了上一题的模板,稳多了,wa了两发是因为数组开小了(╯^╰)
ac:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <set>#include <climits>#include <cassert>#define Min(a,b) ((a)<(b)?(a):(b))#define Max(a,b) ((a)>(b)?(a):(b))#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);const int maxn = 100000 + 10;vector<pair<int, int> > ansQue;int ind[maxn];map<string, int> mp;int dis[maxn], vis[maxn], ancestor[maxn];int ans[maxn];struct Edge{ int to, next; int len;} edge[maxn << 1];int edgeNum;int edgeHead[maxn << 1];void addEdge(int fr, int to, int len){ edge[edgeNum].to = to; edge[edgeNum].len = len; edge[edgeNum].next = edgeHead[fr]; edgeHead[fr] = edgeNum++; edge[edgeNum].to = fr; edge[edgeNum].len = len; edge[edgeNum].next = edgeHead[to]; edgeHead[to] = edgeNum++;}struct Query{ int to, next; int id;} query[maxn << 1];int queryNum;int queryHead[maxn << 1];void addQuery(int fr, int to, int id){ query[queryNum].to = to; query[queryNum].id = id; query[queryNum].next = queryHead[fr]; queryHead[fr] = queryNum++; query[queryNum].to = fr; query[queryNum].id = id; query[queryNum].next = queryHead[to]; queryHead[to] = queryNum++;}int Find(int x){ if (ancestor[x] == x) return x; return ancestor[x] = Find(ancestor[x]);}void lca(int u, int dep, int rt){ ancestor[u] = u; vis[u] = rt; dis[u] = dep; for (int i = edgeHead[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (vis[v] == -1) { lca(v, dep + edge[i].len, rt); ancestor[v] = u; } } for (int i = queryHead[u]; i != -1; i = query[i].next) { int v = query[i].to; if (vis[v] == rt) { ans[query[i].id] = ancestor[Find(v)]; } }}void init(){ edgeNum = 0; queryNum = 0; memset(edgeHead, -1, sizeof(edgeHead)); memset(queryHead, -1, sizeof(queryHead)); memset(vis, -1, sizeof(vis)); memset(ans, -1, sizeof(ans)); memset(ind, 0, sizeof(ind)); ansQue.clear(); mp.clear();}int main(){#ifdef LOCAL freopen("in.txt", "r", stdin);#endif // LOCAL int ncase; scanf("%d", &ncase); while (ncase--) { int n, m; scanf("%d%d", &n, &m); init(); int tot = 1; for (int i = 1; i < n; i++) { string a, b; cin >> a >> b; if (mp.find(a) == mp.end()) { mp[a] = tot++; } if (mp.find(b) == mp.end()) { mp[b] = tot++; } addEdge(mp[b], mp[a], 1); ind[mp[a]]++; } for (int i = 0; i < m; i++) { string a, b; cin >> a >> b; ans[i] = -1; addQuery(mp[a], mp[b], i); ansQue.push_back(make_pair(mp[a], mp[b])); } int rt; for (int i = 1; i <= n; i++) { if (!ind[i]) { rt = i; break; } } lca(rt, 0, rt); for (int i = 0; i < m; i++) { int fr = ansQue[i].first; int to = ansQue[i].second; if (fr == to) { printf("0\n"); } else if (fr == ans[i]) { printf("1\n"); } else if (to == ans[i]) { printf("%d\n", dis[fr] - dis[to]); } else { printf("%d\n", dis[fr] - dis[ans[i]] + 1); } } } return 0;}
ac:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <set>#include <climits>#include <cassert>#define Min(a,b) ((a)<(b)?(a):(b))#define Max(a,b) ((a)>(b)?(a):(b))#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 100000 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);///int ans[maxn];vector<pair<int, int> > ansQue;struct Query{ int to, id; Query(){} Query(int _to, int _id) { to = _to; id = _id; }};map<string, int> mp;int step[maxn];int n;vector<int> edge[maxn];vector<Query> query[maxn];int inDegree[maxn];int ancestor[maxn];bool vis[maxn];int fa[maxn];int Rank[maxn];void Init(int n){ mp.clear(); ansQue.clear(); for (int i = 1; i <= n; i++) { fa[i] = i; Rank[i] = 0; edge[i].clear(); query[i].clear(); } memset(vis, false, sizeof(vis)); memset(inDegree, 0, sizeof(inDegree)); memset(ancestor, 0, sizeof(ancestor)); memset(step, 0, sizeof(step));}int Find(int x){ if (fa[x] != x) fa[x] = Find(fa[x]); return fa[x];}void Union(int u, int v){ int fau = Find(u); int fav = Find(v); if (fau == fav) return; if (Rank[fau] < Rank[fav]) { fa[fau] = fav; } else { fa[fav] = fau; if (Rank[fau] == Rank[fav]) Rank[fau]++; }}void lca(int rt, int num){ //自成集合 step[rt] = num; ancestor[rt] = rt; int sz = edge[rt].size(); for (int i = 0; i < sz; i++) { int v = edge[rt][i]; lca(v, num + 1); //递归子树 Union(rt, v); //合并子树与根 ancestor[Find(v)] = rt; //子树祖先也指向根 } vis[rt] = true; sz = query[rt].size(); for (int i = 0; i < sz; i++) { int fr = rt; int to = query[rt][i].to; int id = query[rt][i].id; if (vis[to]) { ///记录答案时必须要这样。。。否则wa到死。。。 ///ps.I don't know why... ans[id] = ancestor[Find(to)]; } } return;}int main(){#ifdef LOCAL freopen("in.txt", "r", stdin);#endif // LOCAL int ncase; scanf("%d", &ncase); while (ncase--) { int n, m; scanf("%d%d", &n, &m); Init(n); int tot = 1; for (int i = 1; i < n; i++) { string a, b; cin >> a >> b; if (mp.find(a) == mp.end()) { mp[a] = tot++; } if (mp.find(b) == mp.end()) { mp[b] = tot++; } edge[mp[b]].push_back(mp[a]); inDegree[mp[a]]++; } for (int i = 0; i < m; i++) { string a, b; cin >> a >> b; query[mp[a]].push_back(Query(mp[b], i)); query[mp[b]].push_back(Query(mp[a], i)); ansQue.push_back(make_pair(mp[a], mp[b])); } int rt; for (int i = 1; i <= n; i++) { if (!inDegree[i]) { rt = i; break; } } lca(rt, 0); for (int i = 0; i < m; i++) { int fr = ansQue[i].first; int to = ansQue[i].second; if (fr == to) { printf("0\n"); } else if (fr == ans[i]) { printf("1\n"); } else if (to == ans[i]) { printf("%d\n", step[fr] - step[to]); } else { printf("%d\n", step[fr] - step[ans[i]] + 1); } } } return 0;}
wa tarjan离线:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <set>#include <climits>#include <cassert>#define Min(a,b) ((a)<(b)?(a):(b))#define Max(a,b) ((a)>(b)?(a):(b))#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 100000 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);map<string, int> mp;vector<int> ans;vector<pair<int, int> > ansQue;int step[maxn];int n;vector<int> edge[maxn], query[maxn];int inDegree[maxn];int ancestor[maxn];bool vis[maxn];int fa[maxn];int Rank[maxn];void Init(int n){ mp.clear(); ans.clear(); ansQue.clear(); for (int i = 1; i <= n; i++) { fa[i] = i; Rank[i] = 0; edge[i].clear(); query[i].clear(); } memset(vis, false, sizeof(vis)); memset(inDegree, 0, sizeof(inDegree)); memset(ancestor, 0, sizeof(ancestor)); memset(step, 0, sizeof(step));}int Find(int x){ if (fa[x] != x) fa[x] = Find(fa[x]); return fa[x];}void Union(int u, int v){ int fau = Find(u); int fav = Find(v); if (fau == fav) return; if (Rank[fau] < Rank[fav]) { fa[fau] = fav; } else { fa[fav] = fau; if (Rank[fau] == Rank[fav]) Rank[fau]++; }}void lca(int rt, int num){ //自成集合 step[rt] = num; ancestor[rt] = rt; int sz = edge[rt].size(); for (int i = 0; i < sz; i++) { int v = edge[rt][i]; lca(v, num + 1); //递归子树 Union(rt, v); //合并子树与根 ancestor[Find(v)] = rt; //子树祖先也指向根 } vis[rt] = true; sz = query[rt].size(); for (int i = 0; i < sz; i++) { if (vis[query[rt][i]]) { int v = query[rt][i]; ans.push_back(ancestor[Find(v)]); } } return;}void bfs(int rt){ memset(step, -1, sizeof(step)); step[rt] = 1; queue<int> q; q.push(rt); while (!q.empty()) { int now = q.front(); q.pop(); int sz = edge[now].size(); for (int i = 0; i < sz; i++) { int v = edge[now][i]; if (step[v] == -1) { step[v] = step[now] + 1; q.push(v); } } }}int main(){#ifdef LOCAL freopen("in.txt", "r", stdin);#endif // LOCAL int ncase; scanf("%d", &ncase); while (ncase--) { int n, m; scanf("%d%d", &n, &m); Init(n); int tot = 1; for (int i = 1; i < n; i++) { string a, b; cin >> a >> b; if (mp.find(a) == mp.end()) { mp[a] = tot++; } if (mp.find(b) == mp.end()) { mp[b] = tot++; } edge[mp[b]].push_back(mp[a]); inDegree[mp[a]]++; } for (int i = 0; i < m; i++) { string a, b; cin >> a >> b; query[mp[a]].push_back(mp[b]); query[mp[b]].push_back(mp[a]); ansQue.push_back(make_pair(mp[a], mp[b])); }// if (n == 1)// {// for (int i = 0; i < m; i++)// {// printf("0\n");// }// continue;// } int rt; for (int i = 1; i <= n; i++) { if (!inDegree[i]) { rt = i; break; } }// bfs(rt); lca(rt, 0); for (int i = 0; i < m; i++) { int fr = ansQue[i].first; int to = ansQue[i].second; if (fr == to) { printf("0\n"); } else if (fr == ans[i]) { printf("1\n"); } else if (to == ans[i]) { printf("%d\n", step[fr] - step[to]); } else { printf("%d\n", step[fr] - step[ans[i]] + 1); } } } return 0;}
wa st在线:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <set>#include <climits>#include <cassert>#define Min(a,b) ((a)<(b)?(a):(b))#define Max(a,b) ((a)>(b)?(a):(b))#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 100000 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);map<string, int> mp;int ind[maxn];int head[maxn];int edgeNum;struct Edge{ int fr, to, next; int val;} e[maxn << 1];void initEdge(){ memset(head, -1, sizeof(head)); edgeNum = 0;}void addEdge(int fr, int to, int val){ e[edgeNum].fr = fr; e[edgeNum].to = to; e[edgeNum].val = val; e[edgeNum].next = head[fr]; head[fr] = edgeNum++; e[edgeNum].fr = to; e[edgeNum].to = fr; e[edgeNum].val = val; e[edgeNum].next = head[to]; head[to] = edgeNum++;}bool vis[maxn];int dis[maxn]; //根节点到当前点的距离int ver[maxn << 1]; //dfs遍历时节点的编号int dep[maxn << 1]; //dfs遍历时节点的深度int R[maxn]; //dfs遍历时第一次出现当前节点时的遍历序号int tot; //下标计数器void dfs(int u, int d){ vis[u] = true; ver[++tot] = u; R[u] = tot; dep[tot] = d; for (int i = head[u]; i != -1; i = e[i].next) { if (!vis[e[i].to]) { int v = e[i].to; int val = e[i].val; dis[v] = dis[u] + val; dfs(v, d + 1); ver[++tot] = u; dep[tot] = d; } }}//ST算法中保存的是当前段深度最小的节点的序号int minDepVerIndex[maxn << 1][10];// n = (n * 2 - 1)void queryInit(int n){ //////////////////////////// for (int i = 1; i <= n; i++) { minDepVerIndex[i][0] = i; } //////////////////////////// for (int j = 1; (1 << j) <= n; j++) { for (int i = 1; i + (1 << j) - 1 <= n; i++) { int p = (1 << (j - 1)); int u = minDepVerIndex[i][j - 1]; int v = minDepVerIndex[i + p][j - 1]; minDepVerIndex[i][j] = dep[u] < dep[v] ? u : v; } }}int queryMin(int l, int r){ int k = log2((double)(r - l + 1)); int u = minDepVerIndex[l][k]; int v = minDepVerIndex[r - (1 << k) + 1][k]; return dep[u] < dep[v] ? u : v;}int lca(int u, int v){ int l = R[u]; int r = R[v]; if (l > r) swap(l, r); int index = queryMin(l, r); return ver[index];}int main(){#ifdef LOCAL freopen("in.txt", "r", stdin);#endif // LOCAL int ncase; scanf("%d", &ncase); while (ncase--) { int n, m; scanf("%d%d", &n, &m); tot = 1; initEdge(); mp.clear(); memset(ind, 0, sizeof(ind)); for (int i = 1; i < n; i++) { string a, b; cin >> a >> b; if (mp.find(a) == mp.end()) { mp[a] = tot++; } if (mp.find(b) == mp.end()) { mp[b] = tot++; } addEdge(mp[a], mp[b], 1); ind[mp[a]]++; } int rt; for (int i = 1; i <= n; i++) { if (!ind[i]) { rt = i; break; } } memset(vis, false, sizeof(vis)); tot = 0; dis[1] = 0; dfs(rt, 1); queryInit((n << 1) - 1); for (int i = 0; i < m; i++) { string a, b; cin >> a >> b; int fr = mp[a]; int to = mp[b]; int rt = lca(mp[a], mp[b]);// cout << rt << endl; if (fr == to) puts("0"); else if (fr == rt) puts("1"); else if (to == rt) printf("%d\n", dis[fr] - dis[rt]); else printf("%d\n", dis[fr] - dis[rt] + 1); } } return 0;}
0 0
- hdu 4547 Tarjan LCA 离线算法
- hdu 4547 lca-tarjan离线算法
- HDU 2586 LCA离线算法 tarjan算法
- HDU 2874 LCA离线算法 tarjan算法
- LCA 离线算法 tarjan
- LCA 离线tarjan算法
- LCA Tarjan离线算法
- LCA离线算法tarjan
- LCA离线算法Tarjan
- LCA 离线算法: tarjan
- hdu 2586 lca离线tarjan
- hdu 2874 Tarjan离线 LCA
- LCA的Tarjan离线算法
- 图论 LCA离线算法 Tarjan
- LCA离线tarjan算法模板
- LCA的离线算法 tarjan
- tarjan算法 离线求LCA
- HDU4547(tarjan算法 离线LCA)
- FileOutputStream/FileInputStream--FileWriter/FileReader
- 相似图片搜索
- 提示磁盘被写保护怎么办?
- Python中re(正则表达式)模块详解
- 项目开发中用到的一些MySQL语句
- hdu 4547 lca-tarjan离线算法
- 属性名前两个字母要么都是大写的要么都是小写的(当然数字与_、$算小写)
- jQuery 动画、HTML、CSS
- 怎样设计数据库之命名规范
- LintCode-最大子数组 III
- corejava知识---【一】
- POJ3104 Drying
- CSS学习笔记---(四)
- Jsp中复选框的全选与反选