好吧。。我的第二题现在还是挂着,算了,就把第二题无视掉吧,贴一下 ACD 的解题思路。
A
水题,不说太多,直接模拟就可以了,用 a a a 数组表示指定位置的 d d d ,为了防止出现负数,把 x x x 都加了 20000 20000 2 0 0 0 0 ,读取了一个 x x x 和一个 d d d ,判断 a [ x + d ] a[x+d] a [ x + d ] 是否是 − d -d − d 即可,如果是,就说明找到了一对。
我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include <cstdio> #include <cstdlib> #include <cstring> using namespace std;const int step = 20000 ;int a[100000 ];int main () { int n; int x, d; scanf ("%d" , &n); while (n--) { scanf ("%d%d" , &x, &d); x += step; if (a[x + d] == -d) { puts ("YES" ); return 0 ; } else a[x] = d; } puts ("NO" ); return 0 ; }
C
欧拉通路变形,因为要保证每个点都访问到一次,于是就找从奇度数结点出发进行 dfs,运用类似套圈法的方法来把结点加入路径中。
还要注意因为范围很大,所以需要离散化,或者用 map 来存放结点信息。
我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <cstdio> #include <cstring> #include <list> #include <map> #include <string> #include <vector> using namespace std;int n;map<int , list<int > > lst; vector<int > ret; map<int , int > d; map<int , bool > use; void dfs (int u) { int v; list<int >& l = lst[u]; while (!l.empty ()) { v = *(l.begin ()); l.pop_front (); if (!use[v]) dfs (v); } ret.push_back (u); } int main () { int n, s; int x, y; scanf ("%d" , &n); for (int i = 0 ; i < n; i++) { scanf ("%d%d" , &x, &y); lst[x].push_back (y); lst[y].push_back (x); d[x]++; d[y]++; } for (map<int , int >::iterator it = d.begin (); it != d.end (); it++) { if ((it->second) % 2 ) { s = it->first; break ; } } dfs (s); for (int i = 0 ; i < n; i++) printf ("%d " , ret[i]); printf ("%d\n" , ret[n]); return 0 ; }
D
经典 LCA 问题,为了得到有顺序的结点,我们求出相邻的结点的 LCA 即可,建议大家先看相关的资料再理解这个算法。
我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 #include <algorithm> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std;const int MAX = 305 ;int lst[MAX][MAX]; int father[MAX]; bool vis[MAX]; bool leaf[MAX]; int order[MAX]; int lca[MAX]; void dfs (int x) { bool flag = false ; vis[x] = true ; for (int i = 1 ; i <= lst[x][0 ]; i++) { if (!vis[lst[x][i]]) { flag = true ; father[lst[x][i]] = x; dfs (lst[x][i]); } } if (!flag) leaf[x] = true ; } int st[MAX], cnt[MAX][MAX];int ret[600000 ];int main () { int x, y, n; int nleaf, temp, P, top; scanf ("%d" , &n); for (int i = 1 ; i <= n; i++) lst[i][0 ] = 0 ; for (int i = 1 ; i < n; i++) { scanf ("%d%d" , &x, &y); lst[x][0 ]++; lst[x][lst[x][0 ]] = y; lst[y][0 ]++; lst[y][lst[y][0 ]] = x; } for (int i = 1 ; i <= n; i++) { vis[i] = false ; leaf[i] = false ; } father[1 ] = -1 ; dfs (1 ); nleaf = 0 ; for (int i = 1 ; i <= n; i++) if (leaf[i]) nleaf++; for (int i = 1 ; i <= nleaf; i++) scanf ("%d" , &order[i]); for (int i = 1 ; i < nleaf; i++) { for (int j = 1 ; j <= n; j++) vis[j] = false ; temp = order[i]; while (temp != 1 ) { vis[temp] = 1 ; temp = father[temp]; } temp = order[i + 1 ]; vis[1 ] = true ; while (temp != 1 ) { if (vis[temp]) break ; temp = father[temp]; } lca[i] = temp; } order[0 ] = 1 ; lca[0 ] = 1 ; lca[nleaf] = 1 ; order[nleaf + 1 ] = 1 ; for (int i = 1 ; i <= n; i++) for (int j = 1 ; j <= n; j++) cnt[i][j] = 0 ; P = 1 ; ret[0 ] = 1 ; for (int i = 1 ; i <= nleaf; i++) { temp = order[i]; top = 0 ; while (temp != lca[i - 1 ]) { st[top++] = temp; cnt[temp][father[temp]]++; cnt[father[temp]][temp]++; if (cnt[father[temp]][temp] > 2 ) { puts ("-1" ); return 0 ; } temp = father[temp]; } for (int j = top - 1 ; j >= 0 ; j--) ret[P++] = st[j]; temp = order[i]; top = 0 ; while (temp != lca[i]) { st[top++] = temp; cnt[temp][father[temp]]++; cnt[father[temp]][temp]++; if (cnt[father[temp]][temp] > 2 ) { puts ("-1" ); return 0 ; } temp = father[temp]; } st[top] = lca[i]; for (int j = 1 ; j <= top; j++) ret[P++] = st[j]; } for (int i = 0 ; i < P - 1 ; i++) printf ("%d " , ret[i]); printf ("%d\n" , ret[P - 1 ]); }