zoukankan      html  css  js  c++  java
  • 最小生成树

    翻了下之前做过的题,感觉都水的不行=_=||

    The Unique MST

     POJ - 1679

    题意:判断最小生成树是否唯一。

    先求出最小生成树权值ans,用vector记录用的边。

    依次不用vector里记录的边求生成树,若权值等于ans,说明不唯一。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<vector>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 int n,m;
     8 struct edge
     9 {
    10     int u,v,w;
    11     bool operator <(const edge &a) const {
    12     return w<a.w;
    13     }
    14 }e[10010];
    15 int f[110];
    16 int ans;
    17 vector<int>mst;
    18 
    19 void init()
    20 {
    21     for(int i=0;i<=n;i++)
    22         f[i]=i;
    23 }
    24 
    25 int gf(int x)
    26 {
    27     return x==f[x]?x:f[x]=gf(f[x]);
    28 }
    29 
    30 void unit(int x,int y)
    31 {
    32     int px=gf(x);
    33     int py=gf(y);
    34     f[px]=py;
    35 }
    36 
    37 void kru()
    38 {
    39      init();
    40     for(int i=0;i<m;i++)
    41     {
    42         if(gf(e[i].u)!= gf(e[i].v))
    43         {
    44             mst.push_back(i);
    45             ans+=e[i].w;
    46             unit(e[i].u,e[i].v);
    47         }
    48     }
    49 
    50 }
    51 bool yesno()
    52 {
    53     for(int i=0;i<mst.size();i++)
    54     {
    55         int cost=0;
    56           init();
    57           int k=0;
    58         for(int j=0;j<m;j++)
    59         {
    60             if(mst[i]==j) continue;
    61             if(gf(e[j].u)!=gf(e[j].v))
    62         {
    63             cost+=e[j].w;
    64             k++;
    65             unit(e[j].u,e[j].v);
    66         }
    67         }
    68         if(cost==ans&&k==n-1) return 1;
    69     }
    70     return 0;
    71 }
    72 int main()
    73 {
    74     int t;
    75     cin>>t;
    76     while(t--)
    77     {
    78         mst.clear();
    79         ans=0;
    80 
    81         cin>>n>>m;
    82 
    83         for(int i=0;i<m;i++)
    84                 cin>>e[i].u>>e[i].v>>e[i].w;
    85 
    86         sort(e,e+m);
    87         kru();
    88         if(yesno()) cout<<"Not Unique!
    ";
    89         else  cout<<ans<<endl;
    90 
    91     }
    92 }
    View Code

    Slim Span

     UVA - 1395 

    题意:求生成树的最小边权差。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxe=10010;
     4 struct Edge
     5 {
     6     int u,v,w;
     7     bool operator <(const Edge &a)const
     8     {
     9         return w<a.w;
    10     }
    11 }e[maxe];
    12 int n,m;
    13 int slim;
    14 int f[110];
    15 int gf(int x)
    16 {
    17     return x==f[x]?x:f[x]=gf(f[x]);
    18 }
    19 void kruskal(int x)
    20 {
    21     int cnt=0,temp=0;
    22     for(int i=0;i<=n;i++) f[i]=i;
    23     int i;
    24     for(i=x;i<m;i++)
    25     {
    26         int pu=gf(e[i].u);
    27         int pv=gf(e[i].v);
    28         if(pu!=pv)
    29         {
    30             cnt++;
    31             f[pu]=pv;
    32             if(cnt==n-1) break;
    33         }
    34     }
    35     if(cnt!=n-1) return ;
    36     temp=e[i].w-e[x].w;
    37     if(x==0||temp<slim) slim=temp;
    38     return ;
    39 }
    40 
    41 int main()
    42 {
    43     while(scanf("%d%d",&n,&m)&&(n||m))
    44     {
    45         slim=-1;
    46         for(int i=0;i<m;i++)
    47             scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    48         sort(e,e+m);
    49         for(int i=0;i+n-2<m;i++) //
    50         {
    51             kruskal(i);
    52         }
    53         printf("%d
    ",slim);
    54     }
    55 }
    View Code

    Park Visit

     HDU - 4607 

    题意:一个人逛公园,希望看p个景点,景点与路形成一棵树形图,问最少走多少路。

    先求出树的直径:

      从任意一点(一般取第一点)进行bfs,记录下边界a;

      再从a进行bfs,直到边界,记录下长度,即直径。

    然后,如果输入不大于直径,直接输出即可,

      若大于直径,则除了直径上的点,其他要走的都要走一个来回,需要乘2

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 #include<cstdio>
     6 using  namespace std;
     7 const int maxn=1e5+10;
     8 vector<int>node[maxn];
     9 int n , m;
    10 int start,mm;
    11 void dfs(int per,int fro,int len)
    12 {
    13     if(len>mm)
    14     {
    15         mm=len;
    16         start=per;
    17     }
    18     for(int i=0;i<node[per].size();i++)
    19         if(node[per][i]!=fro) dfs(node[per][i],per,len+1);
    20 }
    21 int main()
    22 {
    23     int t;
    24     scanf("%d",&t);
    25     while(t--)
    26     {
    27 
    28        scanf("%d%d",&n,&m);
    29          for(int i=0;i<=n;i++) node[i].clear();
    30         int x,y;
    31         for(int i=0;i<n-1;i++)
    32         {
    33            scanf("%d%d",&x,&y);
    34             node[x].push_back(y);
    35             node[y].push_back(x);
    36         }
    37         start=mm=0;
    38         dfs(1,0,0);
    39         mm=0;
    40         dfs(start,0,0);
    41 
    42         int p;
    43         for(int i=0;i<m;i++)
    44         {
    45             scanf("%d",&p);
    46             if(p<=mm+1) printf("%d
    ",p-1);
    47             else printf("%d
    ",mm+(p-mm-1)*2);
    48         }
    49     }
    50 }
    View Code

    树中的最长路

     HihoCoder - 1050

    题意:求树的直径。

    另一种方法:记录每个点的最长路与次长路,不断更新。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn=100010;
     6 
     7 int md1[maxn],md2[maxn];
     8    //最长     次长
     9 struct node
    10 {
    11     int v;
    12     int nex;
    13 }e[maxn*2];
    14 
    15 
    16 int head[maxn];
    17 int cnt;
    18 
    19 void add(int u,int v)
    20 {
    21     e[cnt].v=v;
    22     e[cnt].nex=head[u];
    23     head[u]=cnt++;
    24 }
    25 
    26 int dfs(int u,int pre)
    27 {
    28     int d;
    29     for(int i=head[u];i!=-1;i=e[i].nex)
    30     {
    31         if(e[i].v==pre) continue;
    32         d=dfs(e[i].v,u)+1;
    33         if(d>md1[u])  //子树最长路大于父亲最长路径
    34         {
    35             md2[u]=md1[u];
    36             md1[u]=d;
    37         }
    38         else if(d>md2[u]) md2[u]=d;  //子树路径只大于次长路径
    39     }
    40     return md1[u];
    41 
    42 }
    43 int main()
    44 {
    45     int n;
    46     int t;
    47     while( scanf("%d",&n)!=EOF)
    48     {
    49         cnt=0;
    50         int u,v;
    51         memset(head,-1,sizeof(head));
    52         memset(md1,0,sizeof(md1));
    53         memset(md2,0,sizeof(md2));
    54         for(int i=1;i<n;i++)
    55         {
    56             scanf("%d%d",&u,&v);
    57             add(u,v);
    58             add(v,u);
    59         }
    60         dfs(1,0);
    61         int ans=0;
    62         for(int i=1;i<=n;i++)
    63             ans=max(ans,md1[i]+md2[i]);
    64         printf("%d
    ",ans);
    65     }
    66 }
    View Code

    Buy or Build

     UVA - 1151 

    题意:求最小生成树。有一些套餐可选,套餐内的边一共只需要一个价钱。

    好像是紫书上的题目。二进制枚举套餐。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<algorithm>
      5 #define ll long long
      6 using namespace std;
      7 vector<int> mst;
      8 const int maxn=1010;
      9 int qsize[10],qcost[10],q[10][maxn];
     10 int x[maxn],y[maxn];
     11 int f[maxn];
     12 int cnt,ans;
     13 
     14 struct edge
     15 {
     16     int u;
     17     int v;
     18     int w;
     19     bool operator < (const edge &a )
     20     {
     21         return w<a.w;
     22     }
     23 }e[maxn*maxn];
     24 
     25 int t,n,m;
     26 void init()
     27 {
     28     for(int i=0;i<=n;i++)
     29         f[i]=i;
     30     ans=0;
     31     cnt=0;
     32     mst.clear();
     33 }
     34 
     35 int gf(int x)
     36 {
     37     return x==f[x]?f[x]:f[x]=gf(f[x]);
     38 }
     39 
     40 void uni(int a,int b)
     41 {
     42     int pa=gf(a);
     43     int pb=gf(b);
     44     f[pa]=pb;
     45 }
     46 
     47 int gd(int i,int j)
     48 {
     49     int dx=x[i]-x[j];
     50     int dy=y[i]-y[j];
     51     return dx*dx+dy*dy;
     52 }
     53 
     54 void add(int u,int v,int w)
     55 {
     56     e[cnt].u=u;
     57     e[cnt].v=v;
     58     e[cnt].w=w;
     59     cnt++;
     60 }
     61 
     62 
     63 void krustal()
     64 {
     65     int coun=0;
     66     for(int i=0;i<cnt;i++)
     67     {
     68         if(gf(e[i].u)!=gf(e[i].v))
     69         {
     70             uni(e[i].u,e[i].v);
     71             ans+=e[i].w;
     72             mst.push_back(i);
     73             coun++;
     74             if(coun==n-1) break;
     75         }
     76     }
     77 }
     78 
     79 void mincost ()
     80 {
     81 
     82     for(int s=1;s<(1<<m);s++)  //枚举
     83     {
     84         int temp=0;
     85         for(int i=0;i<=n;i++) f[i]=i;
     86         for(int i=0;i<m;i++) if(s&(1<<i))
     87         {
     88             temp+=qcost[i];
     89             for(int j=0;j<qsize[i];j++)
     90                 for(int k=j+1;k<qsize[i];k++)
     91                     if(gf(q[i][j])!=gf(q[i][k])) uni(q[i][j],q[i][k]);
     92         }
     93     int len=mst.size();
     94     for(int i=0;i<len;i++)
     95     {
     96         int j=mst[i];
     97         if(gf(e[j].u)!=gf(e[j].v))
     98         {
     99             temp+=e[j].w;
    100             uni(e[j].u,e[j].v);
    101         }
    102     }
    103     ans=min(ans,temp);
    104     }
    105 
    106 
    107 }
    108 
    109 int main()
    110 {
    111     scanf("%d",&t);
    112     while(t--)
    113     {
    114         scanf("%d%d",&n,&m);
    115         init();
    116         for(int i=0;i<m;i++)
    117         {
    118             scanf("%d%d",&qsize[i],&qcost[i]);
    119             for(int j=0;j<qsize[i];j++)
    120                 scanf("%d",&q[i][j]);
    121         }
    122         for(int i=1;i<=n;i++)
    123         {
    124             scanf("%d%d",&x[i],&y[i]);
    125         }
    126         for(int i=1;i<n;i++)
    127             for(int j=i+1;j<=n;j++)
    128              add(i,j,gd(i,j));
    129         sort(e,e+cnt);
    130         krustal();
    131         mincost();
    132         printf("%d
    ",ans);
    133         if(t) printf("
    ");
    134     }
    135 
    136 }
    View Code

    选了这几道重新码一下,其他基本都是很裸的模板题了。。。


  • 相关阅读:
    Coursera机器学习week11 单元测试
    关于 TypeReference 的解释
    getModifiers 方法解释。
    instanceof isInstance isAssignableFrom 比较
    elasticsearch 基础 语法总结
    kibana 启动 关闭 和进程查找
    MD5 SHA1 SHA256 SHA512 SHA1WithRSA 的区别
    spring boot 项目 热启动
    java zip 压缩文件
    Packet for query is too large (1660 > 1024). You can change this value on the server by setting the max_allowed_packet' variable.
  • 原文地址:https://www.cnblogs.com/yijiull/p/7257996.html
Copyright © 2011-2022 走看看