基础,关于Tajan算法解析:https://blog.csdn.net/creatorx/article/details/70739834 (?一下!)
题目大意: Tarjan模板题,找到一对查询顶点的LCA(最近公共祖先)
解题思路就是上面的算法解析
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; const int N = 909; vector<int> mp[N]; //图 vector<int> ask[N]; //查询 bool vis[N]; //标记 bool root[N]; //找根节点 int fa[N]; //并查集 int res[N]; //答案 int n; void init() //初始化 { for(int i = 0; i <= n; i++) { mp[i].clear(); ask[i].clear(); root[i] = 1; vis[i] = 0; res[i] = 0; fa[i] = i; } } //并查集 int Find(int x) { return x == fa[x] ? x : (fa[x] = Find(fa[x])); } void merge(int x, int y) { int t1, t2; t1 = Find(x); t2 = Find(y); if(t1 != t2) fa[t2] = t1; } void tarjan(int u) // tarjan { //从根节点往下,先访问最底下的 再往回 for(int i = 0; i < mp[u].size(); i++) { if(!vis[mp[u][i]]) { //未访问过的点 int v = mp[u][i]; tarjan(v); merge(u,v); //合并 vis[mp[u][i]] = true; //标记已访问 } } for(int i = 0; i < ask[u].size(); i++) { if(vis[ask[u][i]]) { //如果已经访问 int fu = Find(ask[u][i]); res[fu] ++; } } } int main() { while(~scanf("%d",&n)) { int x, y, t; init(); for(int i = 0; i < n; i++) { scanf("%d:(%d)",&x,&y); while(y--) { scanf(" %d",&t); mp[x].push_back(t); root[t] = false; } } scanf("%d",&t); while(t--) { scanf(" (%d%d)",&x,&y); ask[x].push_back(y); ask[y].push_back(x); } for(int i = 1; i <= n; i++) { if(root[i]) { // cout << "root " << i << endl; tarjan(i); break; } } for(int i = 1; i <= n; i++) if(res[i]) printf("%d:%d\n",i,res[i]); } return 0; } /* 9 4:(3) 7 9 8 7:(1) 3 9:(2) 2 6 8:(2) 5 1 3:(0) 2:(0) 6:(0) 5:(0) 1:(0) 6 (2 6) (1 8) (5 8) (2 4) (3 7) (6 1) */
图论使我晕倒... 枯了