题目传送门https://www.nowcoder.com/acm/contest/136#question
本文方法参考官方解题报告
A
这题要注意Htbest往回游时可能被在起点的鲲抓到
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <sstream> #include <algorithm> #include <set> #include <map> #include <vector> #include <queue> #include <iomanip> #include <stack> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; const int MAXN = 1000005; const int MOD = 1e9 + 7; #define MemI(x) memset(x, -1, sizeof(x)) #define Mem0(x) memset(x, 0, sizeof(x)) #define MemM(x) memset(x, 0x3f, sizeof(x)) int L, k, a, b; int main() { scanf("%d%d%d%d", &L, &k, &a, &b); if(b >= a) printf("%.2f ", (double)L / b - (double)L / a); else { double c = 1.0 * k / (a - b); if(2 * c * a >= L - k) printf("%.2f ", (double)L / b - (double)L / a); else printf("%.2f ", 2 * c - (double)L / a); } return 0; }
C
这题是求树的直径,先随便选一个点,然后dfs,找出距离这个点最远的点,它一定是直径的一端,然后再dfs找出另一端
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <sstream> #include <algorithm> #include <set> #include <map> #include <vector> #include <queue> #include <iomanip> #include <stack> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; const int MAXN = 1000005; const int MOD = 1e9 + 7; #define MemI(x) memset(x, -1, sizeof(x)) #define Mem0(x) memset(x, 0, sizeof(x)) #define MemM(x) memset(x, 0x3f, sizeof(x)) struct Edge { int to, next; }edge[MAXN << 1]; int head[MAXN], vis[MAXN]; bool book[MAXN]; int cnt; void Add(int a, int b) { edge[++cnt].to = b; edge[cnt].next = head[a]; head[a] = cnt; } void dfs(int Index, int x) { vis[x] = Index; book[x] = true; for(int i = head[x];i != -1;i = edge[i].next) if(!book[edge[i].to]) dfs(Index + 1, edge[i].to); } int main() { MemI(head); Mem0(vis); int n; scanf("%d", &n); int a, b; for(int i = 0;i < n - 1;++i) { scanf("%d%d", &a, &b); Add(a, b); Add(b, a); } dfs(1, 1); int x, ans = 0; for(int i = 1;i <= n;++i) if(vis[i] > ans) { ans = vis[i]; x = i; } Mem0(vis); Mem0(book); dfs(1, x); for(int i = 1;i <= n;++i) if(vis[i] > ans) ans = vis[i]; printf("%d ", ans); return 0; }
G
这题就简单熟悉下的STL(假装自己熟悉)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <sstream> #include <algorithm> #include <set> #include <map> #include <vector> #include <queue> #include <iomanip> #include <stack> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; const int MAXN = 1000005; const int MOD = 1e9 + 7; #define MemI(x) memset(x, -1, sizeof(x)) #define Mem0(x) memset(x, 0, sizeof(x)) #define MemM(x) memset(x, 0x3f, sizeof(x)) int m, k; //set 自定义去重和排序 //https://www.cnblogs.com/litaozijin/p/6665595.html //其实,set容器在判定已有元素a和新插入元素b是否相等时,是这么做的: //1)将a作为左操作数,b作为有操作数,调用比较函数,并返回比较值 //2)将b作为左操作数,a作为有操作数,再调用一次比较函数,并返回比较值。如果1、2两步的返回值都是false,则认为a、b是相等的,则b不会被插入set容器中;如果1、2两步的返回值都是true,则可能发生未知行为, //因此,记住一个准则:永远让比较函数对相同元素返回false。 struct cmp { bool operator ()(int a, int b) { if(abs(a - b) <= k) return false; return a < b; } }; int main() { scanf("%d%d", &m, &k); set<int, cmp> a; char s[100]; int b; while(m--) { scanf("%s%d", s, &b); if(s[0] == 'a') a.insert(b); else if(s[0] == 'd') a.erase(b); else { if(a.find(b) != a.end()) printf("Yes "); else printf("No "); } } return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <sstream> #include <algorithm> #include <set> #include <map> #include <vector> #include <queue> #include <iomanip> #include <stack> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; const int MAXN = 1000005; const int MOD = 1e9 + 7; #define MemI(x) memset(x, -1, sizeof(x)) #define Mem0(x) memset(x, 0, sizeof(x)) #define MemM(x) memset(x, 0x3f, sizeof(x)) int m, k; int main() { scanf("%d%d", &m, &k); set<int> a; set<int> :: iterator it; char s[100]; int x; while(m--) { scanf("%s%d", s, &x); it = a.lower_bound(x - k); if(s[0] == 'a') { if(it == a.end() || *it > x + k) a.insert(x); } else if(s[0] == 'd') { while(it != a.end() && *it <= x + k) { a.erase(*it); it = a.lower_bound(x - k); } } else { if(it != a.end() && *it <= x + k) printf("Yes "); else printf("No "); } } return 0; }
H
最小生成树
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <sstream> #include <algorithm> #include <set> #include <map> #include <vector> #include <queue> #include <iomanip> #include <stack> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; const int MAXN = 100005; const int MOD = 1e9 + 7; #define MemI(x) memset(x, -1, sizeof(x)) #define Mem0(x) memset(x, 0, sizeof(x)) #define MemM(x) memset(x, 0x3f, sizeof(x)) int n, m; struct Edge { int u, v, w; }edge[MAXN * 5]; int fa[MAXN]; int Find(int x) { if(fa[x] == x) return x; return fa[x] = Find(fa[x]); } bool cmp (const Edge &a, const Edge &b) { return a.w < b.w; } int main() { scanf("%d%d", &n, &m); for(int i = 1;i <= n;++i) fa[i] = i; for(int i = 0;i < m;++i) scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w); sort(edge, edge + m, cmp); int x, y, ans = 0; for(int i = 0;i < m;++i) { x = Find(edge[i].u), y = Find(edge[i].v); if(x != y) { fa[x] = y; ans += edge[i].w; } } printf("%d ", ans); return 0; }