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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

MST(最小生成树)上的确定性和存在性问题

發布時間:2023/12/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MST(最小生成树)上的确定性和存在性问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目1:

給定一個n個點m條邊的連通圖,保證沒有自環和重邊。對于每條邊求出,在其他邊權值不變的情況下,它能取的最大權值,使得這條邊在連通圖的所有最小生成樹上。假如最大權值為無限大,則輸出-1。

題解:

先求出圖的一棵最小生成樹:

對于不在樹上的邊(x,y), 它的權值只要小于樹上x到y路徑中任意一條邊就可以代替這條邊。

對于在樹上的邊(x,y),可以先預處理出所有兩端在x到y路徑上的不在樹上的邊的最小值。它的權值一定要小于最小值。

路徑max和min都可以用倍增求。
時間復雜度O(nlogn)

#include<bits/stdc++.h> using namespace std; const int N=2e5+5; inline int read(){int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m,cnt=0,head[N]; int vis[N],ans[N]; int fa[N],dep[N],id[N]; int f[N][20],maxn[N][20]; struct data{int x,y,dis,id; }a[N]; struct Edge{int v,w,nxt,id; }edge[N<<1]; void add_edge(int u,int v,int w,int id){edge[++cnt].v=v;edge[cnt].w=w;edge[cnt].id=id;edge[cnt].nxt=head[u];head[u]=cnt; } int find(int x){if(fa[x]==x) return fa[x];else return fa[x]=find(fa[x]); } bool cmp(data a,data b){return a.dis<b.dis; } void build(){sort(a+1,a+m+1,cmp);for(int i=1;i<=n;i++) fa[i]=i;for(int i=1;i<=m;i++){int x=a[i].x;int y=a[i].y;if(find(x)!=find(y)){fa[find(x)]=find(y);vis[a[i].id]=1;add_edge(x,y,a[i].dis,a[i].id);add_edge(y,x,a[i].dis,a[i].id);}} } void dfs(int u){for(int i=1;i<=18;i++){f[u][i]=f[f[u][i-1]][i-1];maxn[u][i]=max(maxn[u][i-1],maxn[f[u][i-1]][i-1]);}for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;int w=edge[i].w;if(v==f[u][0]) continue;dep[v]=dep[u]+1;id[v]=edge[i].id;f[v][0]=u;maxn[v][0]=w;dfs(v);} } void solve(int x,int y,int dis){x=find(x);while(dep[x]>dep[y]){ans[id[x]]=min(ans[id[x]],dis-1);int k=find(f[x][0]);fa[x]=k;x=find(x);}//加入新的非樹邊,出現環,要把新出現的環縮成點 } int get(int x,int y,int &lca){int ans=0;if(dep[x]<dep[y]) swap(x,y);for(int i=18;i>=0;i--)if(dep[f[x][i]]>=dep[y]){ans=max(ans,maxn[x][i]);x=f[x][i];}if(x==y){lca=x;return ans;}for(int i=18;i>=0;i--){if(f[x][i]!=f[y][i]){ans=max(ans,maxn[x][i]);ans=max(ans,maxn[y][i]);x=f[x][i],y=f[y][i];}}lca=f[x][0];return max(ans,max(maxn[x][0],maxn[y][0])); } int main(){n=read();m=read();for(int i=1;i<=m;i++){a[i].x=read();a[i].y=read();a[i].dis=read();ans[i]=2e9; a[i].id=i;}build();dfs(1);for(int i=1;i<=n;i++) fa[i]=i;for(int i=1;i<=m;i++){if(!vis[a[i].id]){int x=a[i].x,y=a[i].y,z;ans[a[i].id]=get(x,y,z)-1;solve(x,z,a[i].dis);solve(y,z,a[i].dis);}}for(int i=1;i<=m;i++){if(ans[i]==2e9) printf("-1 ");else printf("%d ",ans[i]);} }

題目2:

題解:

題目的操作其實可以看成給一條邊權值加一

(u[lab],v[lab])這條邊會被算到最小生成樹里面,只有在權值小于等于它的邊加完后,u[lab]和v[lab]不在一個連通塊內。
我們把權值小于等于l[lab]的圖建出來,現在問題變成,你可以用l[lab]?l[i]+1的代價砍掉一些邊使得u[lab]和v[lab]不連通,最小割就好了。

題目3:

給定一個有n個點,m條邊的無向連通圖,每條邊有邊權。 定義一次操作為:選擇一條圖中的邊,并將其權值+1。

試求最小的操作次數,使得操作后的圖的最小生成樹是唯一的。

題解

總結

以上是生活随笔為你收集整理的MST(最小生成树)上的确定性和存在性问题的全部內容,希望文章能夠幫你解決所遇到的問題。

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