日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hdu4912 LCA+贪心

發布時間:2025/6/17 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu4912 LCA+贪心 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ? 給你一棵樹和m條邊,問你在這些邊里面最多能夠挑出多少條邊,使得這些邊之間不能相互交叉。

思路:

? ? ?lca+貪心,首先對于給的每個條邊,我們用lca求出他們的公共節點,然后在公共節點的深度排序,排序之后我們先從最深的開始,每次判斷當前的這條邊的兩點是否用過,如果沒用過,那么就把以當前兩點的公共點為樹根的子樹全部標記上,然后答案+1,就這樣一直遍歷到最后就行了,一開始敲了一個,TLE了,各種優化之后還是TLE了,最后沒辦法了,用了一下自己存的一個LCA的模板,這個比我自己寫的LCA快,所以就AC了,思路就是貪心+LCA。

#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm>#define MAXN 110000 #define MAXM 210000 using namespace std; //********************************************************* int n; struct EDGE {int v, next, w; }edge[MAXM]; int head[MAXN], e; int index, tmpdfn; int f[2 * MAXN], id[MAXN], vis[MAXN], pos[MAXN], dis[MAXN]; int mi[2 * MAXN][18]; void init() {memset(head, -1, sizeof(head));e = 0;index = tmpdfn = 0;memset(vis, 0, sizeof(vis));dis[1] = 0; } void add(int u, int v, int w) {edge[e].v = v;edge[e].w = w;edge[e].next = head[u];head[u] = e++; } void dfs(int u) {vis[u] = 1;int tmp = ++tmpdfn;f[++index] = tmp;id[tmp] = u;pos[u] = index;for(int i = head[u]; i != -1; i = edge[i].next){int v = edge[i].v;if(!vis[v]){dis[v] = dis[u] + edge[i].w;dfs(v);f[++index] = tmp;}} } void rmqinit(int n, int *w) {for(int i = 1; i <= n; i++) mi[i][0] = w[i];int m = (int)(log(n * 1.0) / log(2.0));for(int i = 1; i <= m; i++)for(int j = 1; j <= n; j++){mi[j][i] = mi[j][i - 1];if(j + (1 << (i - 1)) <= n) mi[j][i] = min(mi[j][i], mi[j + (1 << (i - 1))][i - 1]);} } int rmqmin(int l,int r) {int m = (int)(log((r - l + 1) * 1.0) / log(2.0));return min(mi[l][m] , mi[r - (1 << m) + 1][m]); } int LCA(int l, int r) {if(pos[l] > pos[r]) swap(l, r);int ans = rmqmin(pos[l], pos[r]);return id[ans]; } //********************************************************** typedef struct {int a ,b ,ggdeep ,lca; }EDGEE;EDGEE edgee[110000];bool camp(EDGEE a ,EDGEE b) {return a.ggdeep > b.ggdeep; }int use[110000];void mk_dfs(int x) {use[x] = 1;for(int k = head[x] ;k + 1 ;k = edge[k].next){int to = edge[k].v;if(use[to] || dis[x] + 1 != dis[to]) continue;mk_dfs(to);} }int main() { int u, v, w, l, r ,m;while(~scanf("%d%d", &n, &m)){init();for(int i = 1 ;i < n ;i ++){scanf("%d %d" ,&u ,&v);add(u ,v ,1);add(v ,u ,1);}for(int i = 1 ;i <= m ;i ++)scanf("%d %d" ,&edgee[i].a ,&edgee[i].b);dfs(1);rmqinit(index, f);for(int i = 1 ;i <= m ;i ++){int lca = LCA(edgee[i].a ,edgee[i].b);edgee[i].ggdeep = dis[lca];edgee[i].lca = lca;}sort(edgee + 1 ,edgee + m + 1 ,camp);memset(use ,0 ,sizeof(use));int ans = 0;for(int i = 1 ;i <= m ;i ++){if(use[edgee[i].a] || use[edgee[i].b])continue;ans ++;mk_dfs(edgee[i].lca);}printf("%d\n" ,ans); }return 0; }

總結

以上是生活随笔為你收集整理的hdu4912 LCA+贪心的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。