• 最小生成树


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

    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

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


  • 相关阅读:
    全新的ASP.NET !
    asp.net core+ef core
    直播服务器Nginx
    NET Core1
    网络爬虫1
    java thread reuse(good)
    java中Executor、ExecutorService、ThreadPoolExecutor介绍(转)
    小心LinkedHashMap的get()方法(转)
    LinkedHashMap相关信息介绍(转)
    HashTable和HashMap的区别
  • 原文地址:https://www.cnblogs.com/yijiull/p/7257996.html
Copyright © 2020-2023  润新知