PART1(算法思想简介)
1.实现:
2.时间复杂度:
3.特别优势:
4.适用情况:
5.需要注意的点:
6.函数、变量名的解释+英文:
7.dalao分析:
PART2(算法各种类型(并附上代码))
1.代码
#include<cstdio> #include<cmath> #include<algorithm> #include<set> #include<map> #include<cstring> #include<string> #include<vector> #include<queue> #include<iomanip> #include<iostream>#include<stack> using namespace std; #define inf 0x3f3f3f3f const int MAXN = 5e4+10; const int MAXM = 1e5+10; //快读 inline int read(); //与边相关 struct edge { int u, v, next, w; } e[MAXM]; int p[MAXN], eid; inline void InitEdge(); inline void Insert(int u, int v, int w = 0); //lca:先调用LcaPre一次,然后自由调用Lca int dep[MAXN];//深度 int parent[MAXN][20]; void LcaInit(); void LcaDfs(int u); void LcaPre(int n, int root);//n:结点个数,root:根节点 int Lca(int x, int y);//x,y:任意两个结点,返回他们的公共祖先结点 //树上差分 int sum[MAXN]; void TreeNodeDifference(int u, int v, int change); //求最终结果 int ans; void Gmax(int u, int fa); //main int main() { //freopen("in.txt","r", stdin); //freopen("out.txt","w", stdout); ios::sync_with_stdio(false); InitEdge(); int n, k; cin >> n >> k; int u,v; for(int i=1; i<n; i++) { cin>>u>>v; Insert(v, u); Insert(u, v); } LcaPre(n, 1); while(k--) { cin >> u >>v; TreeNodeDifference(u, v, 1); } Gmax(1, -1); cout << ans; return 0; } //函数定义 //快读 inline int read()//快读板子 { int x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') { x=(x<<1)+(x<<3)+c-'0'; c=getchar(); } return x; } inline void InitEdge() { memset(p, -1, sizeof(p)); eid = 0; } inline void Insert(int u, int v, int w) { e[eid].next = p[u]; e[eid].u = u; e[eid].v = v; e[eid].w = w; p[u] = eid++; } //lca void LcaDfs(int u) { for(int i = p[u]; i != -1; i = e[i].next) { if(dep[e[i].v] == -1) { dep[e[i].v] = dep[u]+1; parent[e[i].v][0] = u; LcaDfs(e[i].v); } } } void LcaPre(int n, int root) { LcaInit(); dep[root] = 0; LcaDfs(root); for(int level = 1; (1 << level) <= n; level++) for(int i = 1; i <= n; i++) { parent[i][level] = parent[parent[i][level-1]][level-1]; } } void LcaInit() { memset(dep, -1, sizeof(dep)); } int Lca(int x, int y) { int i, j;//之后求出来的i要使用两次,所以用的时候用j代替i if(dep[x] < dep[y])//x是更深的那个 { swap(x, y); } //找到深度不大于dep[x]的最深的2^i for(i = 0; (1<<i) <= dep[x]; i++); i--; //倍增使得dep[x]==dep[y] for(j = i; j >= 0; j--) { if(dep[x] - (1 << j) >= dep[y]) { x = parent[x][j]; } } //直接y就是x的最近公共祖先 if(x == y) { return x; } //找到公共祖先 for(j = i; j >= 0; j--) { if(parent[x][j] != parent[y][j]) //就是要不相等时才跳,相等时跳那就跳多了而且不行不行 { x = parent[x][j]; y = parent[y][j]; } } return parent[x][0];//因为上面看到相等就不求得跳,所以最终答案是这个!!! } //树上差分 void TreeNodeDifference(int u, int v, int change) { int fa = Lca(u, v); sum[u]+=change, sum[v]+=change; sum[fa]-=change, sum[parent[fa][0]]-=change; } //Gmax void Gmax(int u, int fa) { for(int i = p[u]; ~i; i = e[i].next) { int v = e[i].v; if(v == fa) continue; Gmax(v, u); sum[u] += sum[v]; } ans = max(ans, sum[u]); }
PART3(算法的延伸应用)
PART4(对算法深度的理解)
PART5(与其相关的有趣题目)