• 算法总结


    最短路

    SPFA

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define N 10001
    #define M 500001 
    struct node{
    	int to, w, next;
    }edge[M];
    int cut = 0;
    int head[N];
    int dis[N];
    int n,m,k;
    bool vis[N];
    queue <int> q;
    
    void ini () {
    	fill (dis + 1, dis + N + 1, INT_MAX);
    	memset (head, -1, sizeof (head));
    }
    
    void add (int u, int v, int w) {//建边 
    	cut ++;
    	edge[cut].w = w;
    	edge[cut].to = v;
    	edge[cut].next = head[u];
    	head[u] = cut;
    }
    
    void SPFA (int x) {
    	dis[x] = 0;
    	q.push (x);//头入队 
    	vis[x] = 1;
    	while (! q.empty ()) {
    		int u = q.front(); q.pop(); vis[u] = false;
    		for (int j = head[u]; ~ j; j = edge[j].next) {//调用邻接表 
    			if (dis[edge[j].to] > dis[u] + edge[j].w) {
    				dis[edge[j].to] = dis[u] + edge[j].w;//松弛操作 
    				if (! vis[edge[j].to]) {//判断标记 
    					q.push (edge[j].to);//入队边上的点 
    					vis[edge[j].to] = 1;//标记 
    				}
    			}
    		}
    	}
    } 
    
    int main () {
    	
    	ini ();
    	scanf ("%d %d %d", &n, &m, &k);
    	for (int i = 1, u, v, w; i <= m; i ++) {
    		scanf ("%d %d %d", &u, &v, &w);
    		add (u, v, w);
    	}
    	SPFA (k);
    	for (int i = 1; i <= n; i ++) {
    		printf ("%d ", dis[i]);
    	}
    		
    	return 0;
    }
    

    Dijkstra(堆优化)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define N 10001
    #define M 500001 
    #define P pair<int,int>  
    #define Fi first
    #define Se second
    struct node{
    	int to, w, next;
    }edge[M];
    int cut = 0;
    int head[N];
    int dis[N];
    int n, m, k;
    bool vis[N];
    priority_queue <P, vector<P>, greater<P> > q;//优先队列 
    
    void ini () {
    	fill (dis + 1, dis + N + 1, INT_MAX);
    	memset (head, -1, sizeof (head));
    }
    
    void add (int u, int v, int w) {
    	cut ++;
    	edge[cut].w = w;
    	edge[cut].to = v;
    	edge[cut].next = head[u];
    	head[u] = cut;
    }
    
    void Dij (int x) {
    	dis[x] = 0;
    	vis[x] = 1;
    	q.push (P (0, x));//头入队 
    	while (! q.empty ()) {
    		P u = q.top(); q.pop(); vis[u.Se] = 1;
    		for (int j = head[u.Se]; ~ j; j = edge[j].next) {//邻接表遍历 
    			if (! vis[edge[j].to] && dis[edge[j].to] > dis[u.Se] + edge[j].w) {//判断标记和松弛操作 
    				dis[edge[j].to] = dis[u.Se] + edge[j].w;//松弛 
    				q.push (P (dis[edge[j].to], edge[j].to));//入队 
    			}
    		}
    	}
    } 
    
    int main () {
    	
    	ini ();
    	scanf ("%d %d %d", &n, &m, &k);
    	for (int i=1, u, v, w; i <= m; i ++) {
    		scanf ("%d %d %d", &u, &v, &w);
    		add (u, v, w);
    	}
    	Dij (k); 
    	for (int i = 1; i <= n; i ++) {
    		printf ("%d ", dis[i]);
    	}
    	
    	return 0;
    }
    

    最小生成树

    Kruskal

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define N 5001
    #define M 200001
    struct node {
    	int u, v, w;
    }edge[M];
    int fa[N], n, m;
    
    int find (int x) {//并查集找爸爸 
    	return fa[x] == x ? x : fa[x] = find (fa[x]);
    } 
    
    void un (int x, int y) {//并查集连接 
    	x = find (x);
    	y = find (y);
    	fa[x] = y;
    }
    
    void ini () {//初始化 
    	for (int i = 1; i <= 5000; i ++) fa[i] = i;
    }
    
    bool cmp (node a, node b) {
    	return a.w < b.w;
    }
    
    int main () {
    	
    	ini ();
    	scanf ("%d %d", &n, &m);
    	for (int i = 1; i <= m; i ++) {
    		scanf ("%d %d %d", &edge[i].u, &edge[i].v, &edge[i].w);
    	}
    	sort (edge + 1, edge + m + 1, cmp);
    	int k = 0;
    	int ans = 0;
    	for (int i = 1; i <= m; i ++) {
    		if (find (edge[i].u) != find (edge[i].v)){//判断是否在一个集合里 
    			un (edge[i].u,edge[i].v);
    			k ++;
    			ans += edge[i].w;//累加答案 
    		}
    		if(k == n - 1) break;
    	}
    	if (k == n - 1) printf ("%d", ans);
    	else printf ("orz");//不连通 
    		
        return 0;
    }
    

    排序

    归并排序(求逆序对)

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int n;
    int ans = 0;
    int v[500001];
    int t[500001];
    
    void Qsort (int l, int r) {//归并 
    	if(l == r)return ;
    	int mid = (l + r) >> 1;
    	Qsort (1, mid);
    	Qsort (mid + 1, r);//递归 
    	int i = l; int j = mid + 1; int k = l;
    	while (i <= mid && j <= r) {
    		if (v[i] <= v[j]) t[k ++] = v[i ++];
    		else t[k ++] = v[j ++], ans += mid - i + 1;//数学规律 
    	}
    	while (i <= mid) t[k ++] = v[i ++];
    	while (j <= r) t[k ++] = v[j ++];
    	for (int i = l; i <= r; i ++) v[i] = t[i];
    }
    
    int main () {
    	
    	scanf ("%d", &n);
    	for(int i = 1; i <= n; i ++) scanf ("%d", &v[i]);
    	Qsort (1, n);
    	printf ("%d", ans);
    	
    	return 0;
    }
    

    数据结构

    树状数组(区间查询,区间修改)

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int a[500001], b[500001], c[500001];
    int n, m;
    
    int lowbit (int x) {
    	return x & (-x);
    }
    
    void updata (int i, int k) {
    	int x = i;
    	while (i <= n) {
    		c[i] += k;
    		b[i] += k * (x - 1);
    		i += lowbit (i);
    	}
    }
    
    int getsum (int i) {
    	int sum = 0, x = i;
    	while (i > 0) {
    		sum += x * c[i] - b[i];
    		i -= lowbit (i);
    	}
    	return sum;
    }
    
    //1:区间修改,2:区间查询 
    int main () {
    	
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i ++) {
    		scanf ("%d", &a[i]);
    		updata (i, a[i] - a[i-1]);
    	}
    	for (int i = 1, d, x, y, z; i <= m; i ++) {
    		scanf ("%d", &d);
    		if (d == 1) {
    			scanf ("%d%d%d", &x, &y, &z);
    			updata (x, z);
    			updata (y+1, -z);
    		} else {
    			scanf ("%d%d", &x, &y);
    			printf ("%d
    ", getsum (y) - getsum (x - 1));
    		}
    	}
    	
    	return 0;
    }
    

    链表(尾部插入,遍历)

    struct node {
        int data;
        node *next;
    };
    
    struct list {
        node *head;
        int length;
    };
    
    void add (list &List, int n) {
        node *pcur = new node;
        pcur -> data = n;
        pcur -> next = NULL;
        if (List.head == NULL) {
            List.head = pcur;
            List.length = 1;
        } else {
            node *pt = List.head;
            while (pt -> next != NULL) pt = pt -> next;
            pt -> next = pcur;
            List.length ++;
        }
    }
    
    int main () {
    
        list L;
        L.head = NULL;
        L.length = 0;
        int n;
        cin >> n;
        for (int i = 1; i <= n; i ++) {
            int du;
            cin >> du;
            add (L, du);
        }
        node *bl;
        bl = L.head;
        while (bl != NULL) {
            cout << bl -> data << " ";
            bl = bl -> next;
        }
    
        return 0;
    }
    

    链表 (数组模拟,头尾插,随机插)

    #include <bits/stdc++.h>
    #define LL long long
    
    using namespace std;
    
    struct FastIO {
    	template <typename T> FastIO& operator >> (T& In) {
    		In = 0;
    		char Ch = getchar ();
    		int Flag = 1;
    		for (; ! std :: isdigit (Ch); Ch = getchar ()) if (Ch == '-') Flag = -1;
    		for (;   std :: isdigit (Ch); Ch = getchar ()) In = (In << 3) + (In << 1) + (Ch ^ 48);
    		In *= Flag;
    		return *this;
    	}
    }fin;
    
    const int MaxN = 2010;
    int Val[MaxN], Nxt[MaxN];
    int Head, Size;
    
    void AddHead (int x) {
    	Val[Size] = x;
    	Nxt[Size] = Head;
    	Head = Size;
    	Size ++;
    }
    
    void Init () {
    	Head = -1;
    	Size = 0;
    	AddHead (0);
    }
    
    void AddTail (int x) {
    	Val[Size] = x; 
    	Nxt[Size] = Nxt[Size - 1];
    	Nxt[Size - 1] = Size;
    	Size ++;
    }
    
    void AddRy (int k, int x) {
    	Val[Size] = x;
    	Nxt[Size] = Nxt[k];
    	Nxt[k] = Size;
    	Size ++;
    }
    
    void Delete (int k) {
    	Nxt[k] = Nxt[Nxt[k]];
    }
    
    void Write () {
    	int i = Nxt[Head];
    	for (; i != -1; i = Nxt[i]) printf ("%d ", Val[i]);
    }
    
    int main () {
    	
    	Init ();
        int n;
        fin >> n;
        for (int i = 1; i <= n; i ++) {
        	int x;
        	fin >> x;
        	AddTail (x);
    	}
    	int m;
    	fin >> m;
    	for (int i = 1; i <= m; i ++) {
    		int k, x;
    		fin >> k >> x;
    		AddRy (k, x);
    	}
    	Write ();
        
        return 0; 
    }
    

    线段树 (区间修改,区间查询)

    #include <bits/stdc++.h>
    #define ls (root << 1)
    #define rs (root << 1 | 1)
    #define int long long
    
    using namespace std;
    
    struct FastIO {
    	template <typename T> FastIO& operator >> (T& in) {
    		in = 0;
    		char ch = getchar ();
    		int flag = 1;
    		for (; ! isdigit (ch); ch = getchar ()) if (ch == '-') flag = -1;
    		for (;   isdigit (ch); ch = getchar ()) in = (in << 3) + (in << 1) + (ch ^ 48);
    		in *= flag;
    		return *this;
    	}
    }fin;
    
    const int MaxN = 1e5 + 100;
    int sum[MaxN << 2], l[MaxN << 2], r[MaxN << 2], lz[MaxN << 2], arr[MaxN];
    int n, m;
    
    void pushup (int root) {
    	sum[root] = sum[ls] + sum[rs];
    }
    
    void pushdown (int root) {
    	if (lz[root]) {
    		lz[ls] += lz[root];
    		lz[rs] += lz[root];
    		sum[ls] += lz[root] * (r[ls] - l[ls] + 1);
    		sum[rs] += lz[root] * (r[rs] - l[rs] + 1);
    		lz[root] = 0;
    	}
    }
    
    void build (int root, int L, int R) {
    	l[root] = L;
    	r[root] = R;
    	lz[root] = 0;
    	if (L == R) {
    		sum[root] = arr[L];
    		return ;
    	}
    	int mid = (L + R) >> 1;
    	build (ls, L, mid);
    	build (rs, mid + 1, R);
    	pushup (root);
    }
    
    void add (int root, int L, int R, int k) {
    	if (l[root] >= L && r[root] <= R) {
    		sum[root] += (r[root] - l[root] + 1) * k;
    		lz[root] += k;
    		return ;
    	}
    	if (r[root] < L || l[root] > R) return ;
    	pushdown (root);
    	if (r[ls] >= L) add (ls, L, R, k);
    	if (l[rs] <= R) add (rs, L, R, k);
    	pushup (root);
    }
    
    int search (int root, int L, int R) {
    	if (l[root] >= L && r[root] <= R) return sum[root];
    	if (r[root] < L || l[root] > R) return 0;
    	pushdown (root);
    	int s = 0;
    	if (r[ls] >= L) s += search (ls, L, R);
    	if (l[rs] <= R) s += search (rs, L, R);
    	return s;
    }
    
    main () {
    	
    	fin >> n >> m;
    	for (int i = 1; i <= n; ++ i) fin >> arr[i];
    	build (1, 1, n);
    	for (int i = 1; i <= m; ++ i) {
    		int id;
    		fin >> id;
    		if (id == 1) {
    			int x, y, z;
    			fin >> x >> y >> z;
    			add (1, x, y, z);
    		} else {
    			int x, y;
    			fin >> x >> y;
    			printf ("%lld
    ", search (1, x, y));
    		}
    	}
    	
    	return 0;
    }
    

    Treap

    #include <bits/stdc++.h>
    #define Reg register
    #define RI Reg int
    #define RL Reg LL
    #define RU Reg ull
    #define Con const
    #define CI Con int&
    #define CL Con LL&
    #define CU Con ull&
    #define I inline
    #define W while
    #define LL long long
    #define ull unsigned long long
    
    using namespace std;
    
    struct FastIO {
    	template <typename T> FastIO& operator >> (T& in) {
    		in = 0;
    		char ch = getchar ();
    		int flag = 1;
    		for (; ! std :: isdigit (ch); ch = getchar ()) if (ch == '-') flag = -1;
    		for (;   std :: isdigit (ch); ch = getchar ()) in = (in << 3) + (in << 1) + (ch ^ 48);
    		in *= flag;
    		return *this;
    	}
    }fin;
    
    const int MaxN = 1e6 + 100, INF = 1e9;
    int tot = 0, root = 0;
    struct NODE {
    	int val;
    	int dat;
    	int size;
    	int cnt;
    	int ch[2];
    }nd[MaxN];
    
    int NewNode (int x) { // 创建新节点 
    	++ tot;
    	nd[tot].val = x;
    	nd[tot].dat = rand ();
    	nd[tot].cnt = 1;
    	nd[tot].size = 1;
    	nd[tot].ch[0] = 0;
    	nd[tot].ch[1] = 0;
    	return tot;
    }
    
    void PushUp (int x) { // 更新 
    	nd[x].size = nd[nd[x].ch[0]].size + nd[nd[x].ch[1]].size + nd[x].cnt;
    }
    
    void Build () { // 初始化 
    	root = NewNode (-INF);
    	nd[root].ch[1] = NewNode (INF);
    	PushUp (root);
    }
    
    void Rotate (int &id, int d) { // 旋转     0:左旋      1:右旋 
    	int Tmp = nd[id].ch[d ^ 1];
    	nd[id].ch[d ^ 1] = nd[Tmp].ch[d];
    	nd[Tmp].ch[d] = id;
    	id = Tmp;
    	PushUp (nd[id].ch[d]);
    	PushUp (id);
    }
    
    void Insert (int &id, int x) { // 插入 
    	if (! id) {
    		id = NewNode (x);
    		return ;
    	}
    	if (x == nd[id].val) ++ nd[id].cnt;
    	else {
    		int d = x < nd[id].val ? 0 : 1;
    		Insert (nd[id].ch[d], x);
    		if (nd[id].dat < nd[nd[id].ch[d]].dat) Rotate (id, d ^ 1);
    	}
    	PushUp (id);
    }
    
    void Remove (int &id, int x) { // 删除 
    	if (! id) return ;
    	if (x == nd[id].val) {
    		if (nd[id].cnt > 1) {-- nd[id].cnt; PushUp (id); return ;}
    		if (nd[id].ch[0] || nd[id].ch[1]) {
    			if (! nd[id].ch[1] || nd[nd[id].ch[0]].dat > nd[nd[id].ch[1]].dat) {
    				Rotate (id, 1);
    				Remove (nd[id].ch[1], x);
    			} else {
    				Rotate (id, 0);
    				Remove (nd[id].ch[0], x);
    			}
    			PushUp (id);
    		} else id = 0;
    		return ;
    	}
    	if (x < nd[id].val) Remove (nd[id].ch[0], x);
    	else Remove (nd[id].ch[1], x);
    	PushUp (id);
    }
    
    int Rank (int id, int x) { // 查找x的排名 
    	if (! id) return -2;
    	if (x == nd[id].val) return nd[nd[id].ch[0]].size + 1;
    	else if (x < nd[id].val) return Rank (nd[id].ch[0], x);
    	else return nd[nd[id].ch[0]].size + nd[id].cnt + Rank (nd[id].ch[1], x);
    }
    
    int Val (int id, int rank) { // 查找排名为rank的数 
    	if (! id) return INF;
    	if (rank <= nd[nd[id].ch[0]].size) return Val (nd[id].ch[0], rank);
    	else if (rank <= nd[nd[id].ch[0]].size + nd[id].cnt) return nd[id].val;
    	else return Val (nd[id].ch[1], rank - nd[nd[id].ch[0]].size - nd[id].cnt);
    }
    
    int Pre (int x) { // 查找x的前驱 
    	int id = root, pre;
    	while (id) {
    		if (nd[id].val < x) pre = nd[id].val, id = nd[id].ch[1];
    		else id = nd[id].ch[0];
    	}
    	return pre;
    }
    
    int Next (int x) { // 查找x的后继 
    	int id = root, next;
    	while (id) {
    		if (nd[id].val > x) next = nd[id].val, id = nd[id].ch[0];
    		else id = nd[id].ch[1];
    	}
    	return next;
    }
    
    int n;
    int opt, x;
    //1:插入	2:删除	3:查找x的排名	4:查找排名为rank的数	5:查找x的前驱	6:查找x的后继 
    int main () {
    
    	Build ();
    	fin >> n;
    	for (int i = 1; i <= n; ++ i) {
    		fin >> opt >> x;
    		if (opt == 1) Insert (root, x);
    		else if (opt == 2) Remove (root, x);
    		else if (opt == 3) printf ("%d
    ", Rank (root, x) - 1);
    		else if (opt == 4) printf ("%d
    ", Val (root, x + 1));
    		else if (opt == 5) printf ("%d
    ", Pre (x));
    		else if (opt == 6) printf ("%d
    ", Next (x));
    	}
    	
        return 0;
    }   
    

    fhq_treap

    #include <bits/stdc++.h>
    
    using namespace std;
    
    struct FastIO {
    	template <typename T> FastIO& operator >> (T& in) {
    		in = 0;
    		char ch = getchar ();
    		int flag = 1;
    		for (; ! isdigit (ch); ch = getchar ()) if (ch == '-') flag = -1;
    		for (;   isdigit (ch); ch = getchar ()) in = (in * 10) + (ch ^ 48);
    		in *= flag;
    		return *this;
    	}
    }fin;
    
    const int MaxN = 5e5 + 100;
    int ch[MaxN][2], val[MaxN], rnd[MaxN], size[MaxN], cnt = 0;
    int x, y, z, root = 0;
    int n;
    
    void pushup (int root) {size[root] = size[ch[root][0]] + size[ch[root][1]] + 1;}
    int newnode (int v) {
    	++ cnt;
    	size[cnt] = 1;
    	val[cnt] = v;
    	ch[cnt][0] = ch[cnt][1] = 0;
    	rnd[cnt] = rand ();
    	return cnt;
    }
    
    void split (int now, int k, int &x, int &y) {
    	if (! now) x = y = 0;
    	else {
    		if (val[now] <= k) x = now, split (ch[now][1], k, ch[now][1], y);
    		else y = now, split (ch[now][0], k, x, ch[now][0]);
    		pushup (now);
    	}
    }
    
    int merge (int A, int B) {
    	if (! A || ! B) return A + B;
    	if (rnd[A] < rnd[B]) {ch[A][1] = merge (ch[A][1], B); pushup (A); return A;}
    	else {ch[B][0] = merge (A, ch[B][0]); pushup (B); return B;}
    }
    
    void Insert (int &now, int v) {
    	split (now, v, x, y);
    	now = merge (merge (x, newnode (v)), y);
    }
    
    void Del (int &now, int v) {
    	split (now, v, x, z);
    	split (x, v - 1, x, y);
    	y = merge (ch[y][0], ch[y][1]);
    	now = merge (merge (x, y), z);
    }
    
    int Rank (int &now, int v) {
    	split (now, v - 1, x, y);
    	int res = size[x] + 1;
    	now = merge (x, y);
    	return res;
    }
    
    int Val (int now, int rank) {
    	while (1) {
    		if (rank <= size[ch[now][0]]) now = ch[now][0];
    		else if (rank == size[ch[now][0]] + 1) return val[now];
    		else rank -= size[ch[now][0]] + 1, now = ch[now][1];
    	}
    }
    
    int Pre (int &now, int v) {
    	split (now, v - 1, x, y);
    	int res = Val (x, size[x]);
    	now = merge (x, y);
    	return res;
    }
    
    int Next (int &now, int v) {
    	split (now, v, x, y);
    	int res = Val (y, 1);
    	now = merge (x, y);
    	return res;
    }
    
    int main () {
    	
    	srand (time (0));
    	fin >> n;
    	for (int i = 1; i <= n; ++ i) {
    		int opt, v;
    		fin >> opt >> v;
    		switch (opt) {
    			case 1: Insert (root, v); break;
    			case 2: Del (root, v); break;
    			case 3: printf ("%d
    ", Rank (root, v)); break;
    			case 4: printf ("%d
    ", Val (root, v)); break;
    			case 5: printf ("%d
    ", Pre (root, v)); break;
    			case 6: printf ("%d
    ", Next (root, v)); break;
    		}
    	}
    	
    	return 0;
    }
    

    子序列

    LCS(最长公共子序列)

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define N 100001
    int dp[2][N], a[N], b[N];
    int n; 
    int main(){
    	
    	scanf ("%d", &n);
    	for (int i = 1; i <= n; i ++){
    		scanf ("%d", &a[i]);
    	}
    	for (int i = 1; i <= n; i ++){
    		scanf ("%d", &b[i]);
    	}
    	for (int i = 1; i <= n; i ++){
    		for (int j = 1; j <= n; j ++){
    			if (a[i] != b[j]){
    				dp[i & 1][j] = max (dp[1 - i & 1][j], dp[i & 1][j - 1]);//状态转移方程式 
    			}else{
    				dp[i & 1][j] = dp[1 - i & 1][j - 1] + 1;
    			}
    		}
    	}
    	printf ("%d", dp[n & 1][n]);//滚动数组 
    	
    	return 0;
    }
    

    LIS(最长上升子序列)

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int a[100001], d[100001], n, len;
    int main (){
    	
        scanf ("%d", &n);
        for(int i = 1; i <= n; i ++){
            scanf ("%d", &a[i]);
        }
        d[1] = a[1];
        len = 1;
        for(int i = 2; i <= n; i ++){
            if (a[i] > d[len]) d[++ len] = a[i];
            else{
                int j = upper_bound (d + 1, d + len + 1, a[i]) - d;
                d[j] = a[i];
            }
        }
        printf ("%d", len);
        
        return 0;
    }
    

    LCA

    倍增

    #include <bits/stdc++.h>
    #define DEBUG 0
    
    using namespace std;
    
    struct FastIO {
    	template <typename T> FastIO& operator >> (T& in) {
    		in = 0;
    		char ch = getchar ();
    		int flag = 1;
    		for (; ! isdigit (ch); ch = getchar ()) if (ch == '-') flag = -1;
    		for (;   isdigit (ch); ch = getchar ()) in = (in << 3) + (in << 1) + (ch ^ 48);
    		in *= flag;
    		return *this;
    	}
    }fin;
    
    const int MaxN = 5e5 + 100;
    int n, m, s;
    int head[MaxN], to[MaxN << 1], nxt[MaxN << 1], cnt;
    int lg[MaxN], dep[MaxN], fa[MaxN][25];
    void add (int u, int v) {++ cnt; to[cnt] = v; nxt[cnt] = head[u]; head[u] = cnt;}
    
    void dfs (int now, int fath) {
    	fa[now][0] = fath; dep[now] = dep[fath] + 1;
    	for (int i = 1; i <= lg[dep[now]]; ++ i) fa[now][i] = fa[fa[now][i - 1]][i - 1];
    	for (int i = head[now]; i; i = nxt[i]) {
    		if (to[i] != fath) dfs (to[i], now);
    	}
    }
    
    int LCA (int x, int y) {
    	if (dep[x] < dep[y]) swap (x, y);
    	while (dep[x] > dep[y]) x = fa[x][lg[dep[x] - dep[y]] - 1];
    	if (x == y) return x;
    	for (int i = lg[dep[x]] - 1; i >= 0; -- i) {
    		if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
    	}
    	return fa[x][0];
    }
    
    int main () {
        
        fin >> n >> m >> s;
    	for (int i = 1; i <= n - 1; ++ i) {
    		int x, y;
    		fin >> x >> y;
    		add (x, y); add (y ,x);
    	}
    	for (int i = 1; i <= n; ++ i) lg[i] = lg[i - 1] + (1 << lg[i - 1] == i);
    	dfs (s, 0);
    	for (int i = 1; i <= m; ++ i) {
    		int x, y;
    		fin >> x >> y;
    		printf ("%d
    ", LCA (x, y));
    	}
    
        return 0;
    }
    
  • 相关阅读:
    23种设计模式(3)-原型模式
    23种设计模式(4)-生成器模式
    优秀程序员应具备的15个特性
    23种设计模式(5)-适配器模式
    23种设计模式(6)-装饰者模式
    23种设计模式(7)-代理模式
    SSH框架面试题集锦
    List,Set和Map详解及其区别和他们分别适用的场景
    (转) 网页浏览速度慢的排查原因
    (转)局域网的某个机器无法上网,的排错思路
  • 原文地址:https://www.cnblogs.com/binghun/p/sf.html
Copyright © 2020-2023  润新知