zoukankan      html  css  js  c++  java
  • AIZU AOJ 2309 Vector Compression 最小树形图(朱—刘算法)

    题意简述:给定若干个相同维度的向量,寻找一种排序方法,使得所有向量的表示长度总和最低。 所谓表示长度为(Aj-r*Ai)^2,其中i<j 

    数据范围:向量总数和维度均小于100

    思路:(1)首先Ai和Aj确定后,最小表示长度是可以在线性时间计算出来的。使用简单的二次函数分析方法即可。

             (2)上述可以得出任意两向量之间的距离,即为图中的边,于是问题可以转化为有向图的“最小树形图”,i到j的有向边权值即为用Aj表示Ai的最小表示长度。

             (3)朱-刘算法简述: 首先对除根以外的点选择一条权值最小的边,如果没有构成环且没有孤立点则找到了答案。

                            如果存在环,则将环缩为一个新的点 然后更新所有的边权

                            

                       设环中的点有(Vk1,Vk2,… ,Vki)总共i个,用缩成的点叫Vk替代,则在压缩后的图中,其他所有不在环中点v到Vk的距离定义如下:
                       gh[v][Vk]=min { gh[v][Vkj]-mincost[Vkj] } (1<=j<=i)//由于选择入边必然放弃Vkj之前选择的入边,所以要减去mincost[Vkj]

                       而Vk到v的距离为
                      gh[Vk][v]=min { gh[Vkj][v] }              (1<=j<=i)

                     直到不存在环算法结束得到最优解。

             (4)本题向量序列是任意的,所以对应生成树的根是不确定的,我们可以枚举根,但是复杂度太高。

                 此时我们引入一个 零向量 作为树根 显然任何向量由零向量表示的结果都是最差的,所以对其他的所有点直接运行朱刘算法就可以得到解了。

             PS:这个题用cout输出会WE。。 必须用printf

                  

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<queue>
      7 #include<stack>
      8 #include<vector>
      9 using namespace std;
     10 
     11 
     12 struct edge
     13 {
     14  int begin;int end;    
     15 };
     16 
     17 const int maxx=120;
     18 bool vis[maxx],indfs[maxx];
     19 vector<double>zero;
     20 int n,m,root;
     21 vector<vector<double> >vec;
     22 double cost[maxx][maxx],Cost[maxx][maxx];
     23 bool operator <(const edge a,const edge b)
     24 {
     25  double ac=cost[a.begin][a.end];double bc=cost[b.begin][b.end];
     26  return ac>bc;//从小到大排序    
     27 };
     28 priority_queue<edge>que[maxx];
     29 double minv(vector<double> a,vector<double> b)
     30 {
     31  double ab=0,bsqrt=0,asqrt=0;
     32  for(int i=0;i<a.size();i++)
     33      {ab+=a[i]*b[i];bsqrt+=b[i]*b[i];asqrt+=a[i]*a[i];}
     34      
     35  if((bsqrt-0.0)<1e-10)return asqrt;
     36  return asqrt-(ab*ab/bsqrt);
     37 }
     38 int belongcircle[maxx];
     39 int findbelong(int x)
     40 {
     41  if(x==belongcircle[x])return x;
     42      else return belongcircle[x]=findbelong(belongcircle[x]);
     43 }
     44 
     45 double ans,ansnow;
     46 double min(double a,double b)
     47 {
     48  if(a<b)return a;
     49      else return b;
     50 }
     51 void combinecircle(int now,int begin)
     52 {
     53  now=findbelong(now);
     54  if(vis[now])return ;
     55  vis[now]=true;
     56  edge e1=que[now].top();
     57  double coste=cost[findbelong(e1.begin)][findbelong(e1.end)];
     58  ansnow+=coste;
     59  bool finish[maxx];
     60  memset(finish,0,sizeof(finish));
     61  for(int i=0;i<=m;i++)
     62      {
     63       int po=findbelong(i);
     64       if(po==now||po==begin)continue;
     65       if(finish[po])continue;
     66       finish[po]=true;
     67       cost[begin][po]=min(cost[begin][po],cost[now][po]-coste);
     68       cost[po][begin]=min(cost[po][begin],cost[po][now]);
     69     }
     70  belongcircle[now]=begin;
     71  combinecircle(e1.end,begin);
     72  return ;
     73 }
     74 void build();
     75 bool findcircle(int now)
     76 {
     77  if(now==root)return false; 
     78  now=findbelong(now);
     79  if(indfs[now])
     80      {
     81       memset(vis,0,sizeof(vis));
     82       combinecircle(now,now);
     83       build();
     84       return true;
     85     }
     86  indfs[now]=true;
     87  return findcircle(que[now].top().end);
     88 }
     89 
     90 void build()
     91 {
     92  bool finish[maxx];
     93  memset(finish,0,sizeof(finish));
     94  for(int i=0;i<m;i++)
     95      {
     96       int po=findbelong(i);
     97       if(finish[po])continue;
     98       finish[po]=true;
     99       while(!que[po].empty())que[po].pop();
    100       for(int j=0;j<=m;j++)
    101           {
    102            int pb=findbelong(j);
    103            if(po==pb)continue;
    104            edge en;en.begin=po;en.end=pb;
    105            que[po].push(en);
    106         }
    107     }
    108  return ;
    109 }
    110 bool counted[maxx];
    111 int main()
    112 {freopen("1.txt","r",stdin);
    113  ios::sync_with_stdio(false);
    114  cin>>n>>m;
    115  for(int i=0;i<n;i++)
    116     zero.push_back(0.0);
    117  for(int i=0;i<m;i++)
    118      {
    119      vector<double>nowv;
    120      for(int j=0;j<n;j++)
    121          { double nv;cin>>nv;nowv.push_back(nv);}
    122      vec.push_back(nowv);
    123     }
    124  vec.push_back(zero);
    125  for(int i=0;i<=m;i++)
    126      for(int j=0;j<=m;j++)
    127          { cost[i][j]=minv(vec[i],vec[j]);}
    128  root=m;
    129  ansnow=0;
    130  belongcircle[root]=root;
    131       for(int i=0;i<m;i++)
    132           {
    133            belongcircle[i]=i;
    134           }
    135      bool exis=false;
    136           do
    137               {
    138                build();
    139                exis=false;
    140                bool finish[maxx];
    141                memset(finish,0,sizeof(finish));
    142                for(int i=0;i<m;i++)
    143                {  
    144                 int po=findbelong(i);
    145                 if(finish[po])continue;
    146                   memset(indfs,0,sizeof(indfs));
    147                   exis=findcircle(po);
    148                   finish[po]=true;
    149              }
    150             }while(exis);
    151      memset(counted,0,sizeof(counted));
    152      for(int i=0;i<m;i++)
    153          {
    154          int po=findbelong(i);
    155          if(counted[po])continue;
    156          counted[po]=true;
    157          ansnow+=cost[findbelong(que[po].top().begin)][findbelong(que[po].top().end)];    
    158         }
    159  printf("%lf
    ",ansnow);
    160  return 0;
    161 }

    代码比较乱。。

  • 相关阅读:
    一个matlab小程序:挑出沪市A股年报与一季度报在同一天发布的股票
    AWK
    matlab搜索路径
    从新浪财经上下载交易明细数据并统计每天的买卖笔数(shell 命令行)
    AWK截取字符串
    tar GNU
    工作效率上的错觉(转载)
    matlab双精度浮点数编码及区间覆盖(原创)
    DNS服务器设置(Ubuntu10.04)
    sed
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6389543.html
Copyright © 2011-2022 走看看