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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

HDU - 5452 Minimum Cut(LCA+树上差分)

發布時間:2024/4/11 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU - 5452 Minimum Cut(LCA+树上差分) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出n個點,n-1條邊組成一棵樹,然后再給出m-n-1條邊,組成一個圖,現在要讓我們求最少刪去幾條邊才能讓整個圖不連通,并且要求只能在樹上刪去最多一條邊

題目分析:這個題目的意思有點難懂,大概就是需要刪邊,刪去最少的邊讓整個圖不連通,當我們在一棵樹上繼續加邊的話,必定會形成環,假如我們想讓u-v這里出現斷點,那么我們就需要將u-v這條邊在樹上刪去,然后再將與u和v形成環的邊全部刪除才行,舉個例子,借網上大佬的一組圖方便理解:

?上面這個圖中,實線是樹,虛線是邊,這樣組成了一個圖,若我們想讓2-5出現斷點,則首先必須刪去2-5這條邊,然后再將3-5這條邊刪除,若我們想讓1-2出現斷點,則也是應該先刪去1-2這條邊,然后再刪去3-5這條邊,同理,若我們想讓1-5出現斷點,應該刪去2-5或1-2,同時刪去3-5

?下面這個圖也是一樣的道理,我們可以看出,在樹上增加一條邊u-v,則這條邊會影響到樹上u-v這條路徑上的所有邊

綜上所述,我們就可以在讀入m-n-1條邊的時候,對于u-v這條路徑上的權值維護一下就好了,一開始是想將邊權映射到點權上去,然后用線段樹+樹鏈剖分來維護權值,最后求一下每個點權值取一個最小值就好了,但這樣的話會被這個題卡超時,無奈,只能換一種方法,鯤學長之前提示過,于是我就換成樹上差分來寫這個題,因為dfs序前序遍歷的原因,讓u-lca和lca-v這條邊上的序號是連續的,這樣就可以用樹上差分了,最后在樹上自底向上跑一遍前綴和,然后再跑一邊最小值答案就出來了

不過需要注意一下,這個答案是需要刪掉m-n-1中的多少條邊,還要在最小生成樹中刪去相應的邊,所以最終答案記得加一

對了,需要注意一下:

  • 若是對邊權差分,則應該是val[u]++,val[v]++,val[lca]-=2
  • 若是對點權差分,則應該是val[u]++,val[v]++,val[lca]--,val[fa[lca]]--
  • 這個題目是對邊權差分,采用第一種公式即可

    代碼:

    #include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2e4+100;int n,m,limit;vector<int>node[N];int val[N],sum[N];int dp[N][20],deep[N];void dfs(int u,int f,int dep) {deep[u]=dep;dp[u][0]=f;for(int i=1;i<=limit;i++)dp[u][i]=dp[dp[u][i-1]][i-1];for(auto v:node[u]){if(v==f)continue;dfs(v,u,dep+1);} }int LCA(int a,int b) {if(deep[a]<deep[b])swap(a,b);for(int i=limit;i>=0;i--)if(deep[a]-deep[b]>=(1<<i))a=dp[a][i];if(a==b)return a;for(int i=limit;i>=0;i--)if(dp[a][i]!=dp[b][i]){a=dp[a][i];b=dp[b][i];}return dp[a][0]; }void dfs2(int u,int f) {sum[u]=val[u];for(auto v:node[u]){if(v==f)continue;dfs2(v,u);sum[u]+=sum[v];} }void init() {memset(val,0,sizeof(val));for(int i=1;i<=n;i++)node[i].clear();limit=log2(n)+1; }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int w;cin>>w;int kase=0;while(w--) {scanf("%d%d",&n,&m);init();m-=n-1;for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}dfs(1,0,0);while(m--){int u,v;scanf("%d%d",&u,&v);val[u]++;val[v]++;val[LCA(u,v)]-=2;}dfs2(1,0);int ans=inf;for(int i=2;i<=n;i++)ans=min(ans,sum[i]);printf("Case #%d: %d\n",++kase,ans+1); }return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的HDU - 5452 Minimum Cut(LCA+树上差分)的全部內容,希望文章能夠幫你解決所遇到的問題。

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