1. 程式人生 > 實用技巧 >電話線鋪設——難實現的最小生成樹

電話線鋪設——難實現的最小生成樹

電話線鋪設

輸入

6 9 4
6 3 4
2 5 6
5 4 6
1 3 5
3 5 9
5 6 8
4 1 5
4 6 4
6 2 7
2 5 3
1 5 4
4 5 4
3 2 5

輸出

22
1
8
4
3
1

分析:

這道題打完就A的感覺也太爽了吧,題解待會補,先上程式碼。

程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<vector>
#include
<cstdlib> using namespace std; #define debug printf("zjyvegetable\n") #define int long long inline int read(){ int a=0,b=1;char c=getchar(); while(!isdigit(c)){if(c=='-')b=-1;c=getchar();} while(isdigit(c)){a=a*10+c-'0';c=getchar();} return a*b; } const int N=2e5+50,M=4e5+50,inf=12345678901234
; struct node{ int u,v,val,id; }ed[N],li[N]; bool cmp(node x,node y){ return x.val<y.val; } int n,W,l,t=30,tot,cnt,maxn,rem,sum,ans=inf,where,posi,d[N],F[N], f[N][33],g[N][33],wh[N][33],anss[N]; int h[N],nx[M],ver[M],w[M],pos[M]; int get(int x){ if(F[x]==x)return x; else return F[x]=get
(F[x]); } void mer(int x,int y){ F[get(x)]=get(y); } void add(int u,int v,int z,int whe){ ver[++cnt]=v;w[cnt]=z;pos[cnt]=whe; nx[cnt]=h[u];h[u]=cnt; } queue<int>q; void bfs(){ d[1]=1;q.push(1); while(q.size()){ int x=q.front();q.pop(); for(int i=h[x];i;i=nx[i]){ int v=ver[i]; if(d[v])continue; q.push(v); d[v]=d[x]+1; f[v][0]=x; g[v][0]=w[i]; wh[v][0]=pos[i]; for(int j=1;j<=t;j++){ f[v][j]=f[f[v][j-1]][j-1]; if(g[v][j-1]>g[f[v][j-1]][j-1]){ g[v][j]=g[v][j-1]; wh[v][j]=wh[v][j-1]; } else{ g[v][j]=g[f[v][j-1]][j-1]; wh[v][j]=wh[f[v][j-1]][j-1]; } } } } } void lca(int x,int y){ maxn=0; if(d[x]>d[y])swap(x,y); for(int i=t;i>=0;i--){ if(d[f[y][i]]>=d[x]){ if(g[y][i]>maxn){ maxn=g[y][i]; rem=wh[y][i]; } y=f[y][i]; } } if(x==y)return; for(int i=t;i>=0;i--){ if(f[y][i]!=f[x][i]){ if(g[y][i]>maxn){ maxn=g[y][i]; rem=wh[y][i]; } if(g[x][i]>maxn){ maxn=g[x][i]; rem=wh[x][i]; } x=f[x][i];y=f[y][i]; } } if(g[y][0]>maxn){ maxn=g[y][0]; rem=wh[y][0]; } if(g[x][0]>maxn){ maxn=g[x][0]; rem=wh[x][0]; } } void solve1(){ bfs(); for(int i=1;i<=l;i++){ lca(li[i].u,li[i].v); if(sum-maxn+li[i].val<ans){ ans=sum-maxn+li[i].val; where=rem; posi=i; } } printf("%lld\n",ans); for(int i=1;i<=n-1;i++){ if(anss[i]==where)continue; printf("%lld\n",anss[i]); } printf("%lld\n",posi); exit(0); } void solve2(){ int x,y,minn=inf; for(int i=1;i<=l;i++){ x=get(li[i].u);y=get(li[i].v); if(x==y)continue; if(li[i].val<minn){ minn=li[i].val; rem=i; } } printf("%lld\n",sum+minn); for(int i=1;i<=n-2;i++) printf("%lld\n",anss[i]); printf("%lld\n",rem); exit(0); } signed main(){ freopen("telephone.in","r",stdin); freopen("telephone.out","w",stdout); n=read();W=read();l=read(); for(int i=1;i<=W;i++){ ed[i].u=read(); ed[i].v=read(); ed[i].val=read(); ed[i].id=i; } for(int i=1;i<=n;i++) F[i]=i; int x,y; sort(ed+1,ed+W+1,cmp); for(int i=1;i<=W;i++){ x=get(ed[i].u);y=get(ed[i].v); if(x==y)continue; mer(x,y); sum+=ed[i].val; add(ed[i].u,ed[i].v,ed[i].val,ed[i].id); add(ed[i].v,ed[i].u,ed[i].val,ed[i].id); anss[cnt/2]=ed[i].id; } for(int i=1;i<=l;i++){ li[i].u=read();li[i].v=read(); li[i].val=read(); } if(cnt/2<n-1)solve2(); else solve1(); return 0; }