标签:hdu input lag nbsp int namespace for ref cstring
任意门:http://acm.hdu.edu.cn/showproblem.php?pid=2586
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 24439 Accepted Submission(s): 9739
给一颗 N 个结点,N-1条边的树,和 M 次查询(离线)
要查询两点到最近公共祖先的距离和,首先要预处理出根结点到各个结点的距离(DFS)
然后 Tarjan 找出最近的公共祖先,两个结点到根结点的距离之和减去两倍的最近公共祖先到根结点的距离就是该查询的答案了。
AC code:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 #define INF 0x3f3f3f3f 7 #define LL long long 8 const int MAX_N = 4e4+5; 9 using namespace std; 10 11 struct Edge{int v, nxt, w;}edge[MAX_N<<1]; //静态邻接表 12 struct Query 13 { 14 int v, id; 15 Query(){}; 16 Query(int _v, int _id):v(_v), id(_id){}; 17 }; 18 19 vector<Query> q[MAX_N]; // !!! //查询关系动态二维矩阵 20 21 int head[MAX_N], cnt; //静态邻接表头节点,边数 22 int dis[MAX_N]; //各结点到根结点的距离 23 int fa[MAX_N]; //并查集 祖先数组 24 bool vis[MAX_N], in[MAX_N]; //深搜用,找根结点用 25 int ans[MAX_N]; // !!! //各查询答案 26 int N, M; //结点数,查询数 27 28 void init() 29 { 30 memset(head, -1, sizeof(head)); //初始化 31 memset(vis, false, sizeof(vis)); 32 memset(in, false, sizeof(in)); 33 memset(dis, 0, sizeof(dis)); 34 memset(ans, 0, sizeof(ans)); 35 cnt = 0; 36 } 37 38 void AddEdge(int from, int to, int weight) //静态邻接表加边操作 39 { 40 edge[cnt].v = to; 41 edge[cnt].w = weight; 42 edge[cnt].nxt = head[from]; 43 head[from] = cnt++; 44 } 45 46 int getfa(int x) //找祖先 47 { 48 int root = x; 49 while(fa[root] != root) root = fa[root]; 50 51 int tmp; 52 while(fa[x] != root){ 53 tmp = fa[x]; 54 fa[x] = root; 55 x = tmp; 56 } 57 return root; 58 } 59 60 void dfs(int s) //预处理各根结点到祖先的距离 61 { 62 int rt = s; 63 for(int i = head[s]; i != -1; i = edge[i].nxt){ 64 dis[edge[i].v] = dis[rt] + edge[i].w; 65 dfs(edge[i].v); 66 } 67 } 68 69 void Tarjan(int s) // LCA 70 { 71 int root = s; 72 fa[s] = s; 73 for(int i = head[s]; i != -1; i = edge[i].nxt){ 74 int Eiv = edge[i].v; 75 Tarjan(Eiv); 76 fa[getfa(Eiv)] = s; 77 } 78 vis[s] = true; 79 for(int i = 0; i < q[s].size(); i++){ 80 if(vis[q[s][i].v] && !ans[q[s][i].id]){ 81 ans[q[s][i].id] = dis[q[s][i].v] + dis[s] - 2*dis[getfa(q[s][i].v)]; 82 } 83 } 84 } 85 86 int main() 87 { 88 int T_case; 89 scanf("%d", &T_case); 90 while(T_case--){ 91 init(); 92 scanf("%d %d", &N, &M); 93 for(int i = 1, u, v, w; i < N; i++){ //建树 94 scanf("%d %d %d", &u, &v, &w); 95 AddEdge(u, v, w); 96 in[v] = true; 97 } 98 99 for(int i = 1, u, v; i <= M; i++){ //储存查询信息(离线) 100 scanf("%d %d", &u, &v); 101 q[u].push_back(Query(v, i)); 102 q[v].push_back(Query(u, i)); 103 } 104 105 int root = 0; 106 for(int i = 1; i <= N; i++) if(!in[i]){root = i; break;} //找树根结点 107 108 dfs(root); //预处理 109 Tarjan(root); //LCA 110 111 for(int i = 1; i <= M; i++){ 112 printf("%d\n", ans[i]); 113 } 114 //puts(""); 115 } 116 return 0; 117 }
标签:hdu input lag nbsp int namespace for ref cstring
原文地址:https://www.cnblogs.com/ymzjj/p/9744756.html