zoukankan      html  css  js  c++  java
  • POJ 3164 Command Network(最小树形图模板题+详解)

    http://poj.org/problem?id=3164

    题意:

    求最小树形图。

    思路:

    套模板。

    引用一下来自大神博客的讲解:http://www.cnblogs.com/acjiumeng/p/7136604.html

    算法步骤如下:

    1.判断图的连通性,若不连通直接无解,否则一定有解。

    2.为除了根节点以外的所有点选择一个权值最小的入边,假设用pre数组记录前驱,f数组记录选择的边长,记所选边权和为temp。

    3.(可利用并查集)判断选择的的边是否构成环,若没有则直接$ans+=temp$并输出ans,若有,则进行下一步操作。

    4.对该环实施缩点操作,设该环上有点$V1,V2……Vi……Vn$,缩成的点为node ,对于所有不在环中的点P进行如下更改:

    (1) 点P到node的距离为min{$a[p,Vi]-f[Vi]$} (a为边集数组)

     (2)点node到p的距离为min{$a[Vi,p]$}

    操作(1)的理解:先假设环上所有边均选上,若下次选择某一条边进入该环,则可以断开进入点与进入点的前驱之间的边,即断开F[进入点],所以等效为直接把$a[p,node]$赋值为min{$a[p,Vi]-f[Vi]$}。

    特别提醒:本题有自环,可以提前删掉,因为它没有用。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<sstream>
      6 #include<vector>
      7 #include<stack>
      8 #include<queue>
      9 #include<cmath>
     10 #include<map>
     11 #include<set>
     12 using namespace std;
     13 typedef long long ll;
     14 typedef pair<int,ll> pll;
     15 const int inf = 0x3f3f3f3f;
     16 const int maxn=1000+5;
     17 const int mod=1e9+7;
     18 
     19 int n, m;
     20 
     21 struct point
     22 {
     23     double x,y;
     24 }p[maxn];
     25 
     26 struct node
     27 {
     28     int u,v;
     29     double w;
     30 }edge[maxn*maxn];
     31 
     32 int pre[maxn],id[maxn],use[maxn];
     33 double in[maxn];
     34 
     35 double dis(point a,point b)
     36 {
     37     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
     38 }
     39 
     40 double mini_tree(int root,int n,int m)//分别是树根,节点数,边数,序号从1开始
     41 {
     42     double ans=0;
     43     int u;
     44     while(true)
     45     {
     46         for(int i=1;i<=n;i++)  in[i]=inf;
     47         for(int i=1;i<=m;i++)
     48         {
     49             int u=edge[i].u;
     50             int v=edge[i].v;
     51             if(edge[i].w<in[v]&&u!=v)
     52             {
     53                 in[v]=edge[i].w;
     54                 pre[v]=u;
     55             }
     56         }//找最小的入边
     57         for(int i=1;i<=n;i++)
     58         {
     59             if(i==root)continue;
     60             ans+=in[i];//把边权加起来
     61             if(in[i]==inf)//如果存在没有入弧的点则不存在最小树形图
     62                 return -1;
     63         }
     64         memset(id,-1,sizeof(id));
     65         memset(use,-1,sizeof(use));
     66         int cnt=0;
     67         for(int i=1;i<=n;i++)//枚举每个点,搜索找环
     68         {
     69             int v=i;
     70             while(v!=root&&use[v]!=i&&id[v]==-1)
     71             {
     72                 use[v]=i;
     73                 v=pre[v];
     74             }
     75             if(v!=root&&id[v]==-1)//当找到环的时候缩点编号
     76             {
     77                 ++cnt;
     78                 id[v]=cnt;
     79                 for(u=pre[v];u!=v;u=pre[u])
     80                     id[u]=cnt;
     81             }
     82         }
     83         if(cnt==0)//如果没有环结束程序
     84             break;
     85         for(int i=1;i<=n;i++)//把余下的不在环里的点编号
     86             if(id[i]==-1)
     87                 id[i]=++cnt;
     88         for(int i=1;i<=m;i++)//建立新的图
     89         {
     90             int u=edge[i].u;
     91             int v=edge[i].v;
     92             edge[i].u=id[u];
     93             edge[i].v=id[v];
     94             if(edge[i].u!=edge[i].v)
     95                 edge[i].w-=in[v];
     96         }
     97         n=cnt;//更新节点数和根节点的编号
     98         root=id[root];
     99     }
    100     return ans;
    101 }
    102 
    103 int main()
    104 {
    105     //freopen("in.txt","r",stdin);
    106     while(~scanf("%d%d",&n,&m))
    107     {
    108         for(int i=1;i<=n;i++)  scanf("%lf%lf",&p[i].x,&p[i].y);
    109         for(int i=1;i<=m;i++)
    110         {
    111             scanf("%d%d",&edge[i].u,&edge[i].v);
    112             if(edge[i].u!=edge[i].v)
    113                 edge[i].w=dis(p[edge[i].u],p[edge[i].v]);
    114             else edge[i].w=inf;
    115         }
    116         double ans=mini_tree(1,n,m);
    117         if(ans==-1)  printf("poor snoopy
    ");
    118         else printf("%.2f
    ",ans);
    119     }
    120     return 0;
    121 }
  • 相关阅读:
    大数据概述 106
    编译原理学习随笔 106
    我与ruby第一次接触
    xml在joomla表单中的应用详解
    joomla2.5传统组件开发解析
    joomla2.5开发系列教程原创(1)2.5与1.5异同点
    CSS2简写和常用css总结笔记
    C语言开发php扩展链接库初学
    ruby转战Ubuntu,真折腾?
    joomla搜索功能开发和结果分页探讨
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7390646.html
Copyright © 2011-2022 走看看