首页 > 代码库 > AIZU AOJ 2309 Vector Compression 最小树形图(朱—刘算法)

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\n",ansnow);
160  return 0;
161 }

代码比较乱。。

AIZU AOJ 2309 Vector Compression 最小树形图(朱—刘算法)