• 蓝书3.1 最小生成树


    T1 井 luogu 1550

    题目大意:

    n个点 需要给每个点供水 在给第i个点供水需要花费v i

    连接i号点和j号点 P_ij  求给所有点供水的最小代价

    思路:

    建立一个新节点 对所有点连接v i 边权的长度

    然后跑kruskal

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 2139062143
    10 #define ll long long
    11 #define MAXN 96100
    12 #define eps 1e-5
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 int n,m;
    22 struct edge{int u,v,val;}e[MAXN];
    23 bool cmp(edge a,edge b) {return a.val<b.val;}
    24 int fa[310];
    25 int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
    26 int ok(int u,int v)
    27 {
    28     int fu=find(u),fv=find(v);
    29     if(fu==fv) return 1;
    30     fa[fv]=fu;return 0;
    31 }
    32 void kruskal()
    33 {
    34     int cnt=0,ans=0;
    35     sort(e+1,e+m+1,cmp);
    36     for(int i=1;i<=m;i++)
    37         if(cnt==n) break;
    38         else if(!ok(e[i].u,e[i].v)) {cnt++,ans+=e[i].val;}
    39     printf("%d",ans);
    40 }
    41 int main()
    42 {
    43     n=read(),fa[n+1]=n+1;
    44     for(int i=1;i<=n;i++) fa[i]=i,e[++m].val=read(),e[m].u=i,e[m].v=n+1;
    45     for(int i=1;i<=n;i++)
    46         for(int j=1;j<=n;j++) e[++m].val=read(),e[m].u=i,e[m].v=j;
    47     kruskal();
    48 }
    View Code

    T2 最小完全图 codevs 2796

    题目大意:

    给一个MST 求一个完全图 该完全图使该MST唯一的最小完全图

    思路:

    将边排序 则每次合并两个联通块的时候只需要连sz[a]*sz[b]-1条长度为该树边权值+1的边即可

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 2139062143
    10 #define ll long long
    11 #define MAXN 610*(1<<12)
    12 using namespace std;
    13 inline int read()
    14 {
    15     int x=0,f=1;char ch=getchar();
    16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    18     return x*f;
    19 }
    20 struct edge{int u,v,val;}e[MAXN];
    21 bool cmp(edge a,edge b) {return a.val<b.val;}
    22 int n,fa,fb,T,f[MAXN],sz[MAXN];
    23 ll ans;
    24 int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
    25 int main()
    26 {
    27     n=read();
    28     for(int i=1;i<n;i++) e[i].u=read(),e[i].v=read(),e[i].val=read(),f[i]=i,sz[i]=1,ans+=e[i].val;
    29     f[n]=n,sz[n]=1;
    30     sort(e+1,e+n,cmp);
    31     for(int i=1;i<n;i++)
    32     {
    33         fa=find(e[i].u),fb=find(e[i].v);
    34         f[fa]=fb;
    35         ans+=(ll)(sz[fa]*sz[fb]-1)*(e[i].val+1);
    36         sz[fb]+=sz[fa];
    37     }
    38     printf("%lld
    ",ans);
    39 }
    View Code

    T3 次小生成树  bzoj 1977

    题目大意:

    求严格次小生成树

    思路:

    每次枚举一个非树边  将这条边连接的两个点在树上路径上权值最大的边替换为这个边

    因为是严格次小 所以如果这条边与权值最大的边边权相等 需要使用次大值

    则该情况下生成树权值为原最小生成树权值-树边+非树边

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 2139062143
    10 #define ll long long
    11 #define MAXN 100100
    12 #define eps 1e-5
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 int n,m;
    22 struct edge{int u,v,val,flag;}e[MAXN<<2];
    23 bool cmp(edge a,edge b) {return a.val<b.val;}
    24 int to[MAXN<<1],nxt[MAXN<<1],val[MAXN<<1],fst[MAXN],cnt,fa[MAXN];
    25 inline void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
    26 inline int find(int x) {return x==fa[x]?fa[x]:fa[x]=find(fa[x]);}
    27 int f[MAXN][20],mx[MAXN][20],dep[MAXN],submx[MAXN][20],in[MAXN<<2];
    28 ll ans,Ans=214748364700000000LL;
    29 void kruskal()
    30 {
    31     for(int i=1;i<=m;i++)
    32     {
    33         int u=e[i].u,v=e[i].v;
    34         int f1=find(u),f2=find(v);
    35         if(f1!=f2) {fa[f1]=f2,in[i]=1,ans+=e[i].val;add(u,v,e[i].val);add(v,u,e[i].val);}
    36     }
    37 }
    38 inline void dfs(int x,int p)
    39 {
    40     for(int i=1;i<=18;i++)
    41     {
    42         if((1<<i)>=dep[x]) break;
    43         f[x][i]=f[f[x][i-1]][i-1];
    44         mx[x][i]=max(mx[x][i-1],mx[f[x][i-1]][i-1]);
    45         if(mx[x][i-1]==mx[f[x][i-1]][i-1]) submx[x][i]=max(submx[x][i-1],submx[f[x][i-1]][i-1]);
    46         else submx[x][i]=max(max(submx[x][i-1],submx[f[x][i-1]][i-1]),min(mx[x][i-1],mx[f[x][i-1]][i-1]));
    47     }
    48     for(int i=fst[x];i;i=nxt[i])
    49         if(to[i]!=p) {dep[to[i]]=dep[x]+1,f[to[i]][0]=x;mx[to[i]][0]=val[i];dfs(to[i],x);}
    50 }
    51 inline void solve(ll u,ll v,ll w)
    52 {
    53     int res=0;
    54     if(dep[u]<dep[v]) swap(u,v);
    55     int t=dep[u]-dep[v];
    56     for(int i=18;i>=0;i--) 
    57         if(t&(1<<i))
    58         {
    59             if(mx[u][i]!=w) res=max(res,mx[u][i]);
    60             else res=max(res,submx[u][i]);
    61             u=f[u][i];
    62         }
    63     for(int i=18;i>=0;i--)
    64         if(f[u][i]!=f[v][i])
    65         {
    66             if(mx[u][i]!=w) res=max(res,mx[u][i]);
    67             else res=max(res,submx[u][i]);
    68             if(mx[v][i]!=w) res=max(res,mx[v][i]);
    69             else res=max(res,submx[v][i]);
    70             u=f[u][i],v=f[v][i];
    71         }
    72     if(u!=v)
    73     {
    74         if(mx[u][0]!=w) res=max(res,mx[u][0]);
    75         else res=max(res,submx[u][0]);
    76         if(mx[v][0]!=w) res=max(res,mx[v][0]);
    77         else res=max(res,submx[v][0]);
    78     }
    79     if(res) Ans=min(Ans,w-res);
    80 }
    81 int main()
    82 {
    83     n=read(),m=read();
    84     for(int i=1;i<=n;i++) fa[i]=i;
    85     for(int i=1;i<=m;i++) e[i].u=read(),e[i].v=read(),e[i].val=read();
    86     sort(e+1,e+m+1,cmp);
    87     kruskal();dfs(1,0);
    88     for(int i=1;i<=m;i++) if(!in[i]) solve(e[i].u,e[i].v,e[i].val);
    89     printf("%lld
    ",ans+Ans);
    90 }
    View Code

    T4 tree bzoj 2654

    题解链接

    T5 最小生成树计数 bzoj 1016

    题解链接

  • 相关阅读:
    数据汇总计算和分析的反思
    排名算法计算
    仿Spring读取配置文件实现方案
    xml 配置文件规范 校验
    批量插入数据(基于Mybatis的实现-Oracle)
    shallow copy 和 deep copy 的示例
    引用对象的使用和易产生bug的示例
    codis安装手册
    Redis安装手册
    map和list遍历基础
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9353276.html
Copyright © 2020-2023  润新知