藏宝图

Posted A_LEAF

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了藏宝图相关的知识,希望对你有一定的参考价值。

背景
Czy 爬上黑红树,到达了一个奇怪的地方……
题目描述
Czy 发现了一张奇怪的藏宝图。图上有n 个点,m 条无向边。已经标出了图中两两之
间距离dist。但是czy 知道,只有当图刚好又是一颗树的时候,这张藏宝图才是真的。如
果藏宝图是真的,那么经过点x 的边的边权平均数最大的那个x 是藏着宝物的地方。请计
算这是不是真的藏宝图,如果是真的藏宝之处在哪里。
格式
输入数据第一行一个数T,表示T 组数据。
对于每组数据,第一行一个n,表示藏宝图上的点的个数。
接下来n 行,每行n 个数,表示两两节点之间的距离。
输出一行或两行。第一行”Yes”或”No”,表示这是不是真的藏宝图。
若是真的藏宝图,第二行再输出一个数,表示哪个点是藏宝之处。
样例输入
230
7 9
7 0 2
9 2 0

0 2 7
2 0 9
7 9 0
样例输出
Yes
1
Yes
3
样例解释:第一棵树的形状是1--2--3。1、2 之间的边权是7,2、3 之间是2。
第二棵树的形状是2--1--3。2、1 之间的边权是2,1、3 之间是7。
数据范围
对于30%数据,n<=50,1<=树上的边的长度<=10^9。
对于50%数据,n<=600.
对于100%数据,1<=n<=2500,除30%小数据外任意0<=dist[i][j]<=10^9,T<=5

 

solution:

树的性质:有n个点,n-1条边。

给的矩阵不是树,就是图

先跑一边最小生成树,再用O(n^2)求出最小生成树上各点之间的距离,得到一个新的矩阵

再将新得到的矩阵与原来的 进行对比,如果不同,说明是图

至于最小生成树,这题卡kruskar的O(n^2*logn),用prim O(n^2)

 

技术分享
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<cmath>
  5 #include<algorithm>
  6 #define ll long long
  7 #define mem(a,b) memset(a,b,sizeof(a))
  8 #define dd double
  9 using namespace std;
 10 int read()
 11 {
 12     int ans=0;char q=getchar();
 13     while(q<0||q>9)q=getchar();
 14     while(q>=0&&q<=9){ans=ans*10+q-0;q=getchar();}
 15     return ans;
 16 }
 17 
 18 int T;
 19 int n;
 20 ll a[2505][2505];
 21 ll d[2505];
 22 int vis[2505],qian[2505];
 23 ll a2[2505][2505];
 24 struct son1
 25 {
 26     int v,next;
 27     ll w;
 28 };
 29 son1 a1[10001];
 30 int first[10001],e;
 31 void addbian(int u,int v,ll w)
 32 {
 33     a1[e].w=w;
 34     a1[e].v=v;
 35     a1[e].next=first[u];
 36     first[u]=e++;
 37 }
 38 
 39 void clear()
 40 {
 41     mem(d,0x7f);
 42     mem(first,-1);
 43     e=0;
 44     mem(a1,0);
 45     mem(a2,0);
 46     mem(vis,0);
 47     mem(qian,0);
 48 }
 49 
 50 void dfs(int fa,int x,int now)
 51 {
 52     for(int i=first[x];i!=-1;i=a1[i].next)
 53     {
 54         int temp=a1[i].v;
 55         if(temp==fa)continue;
 56         a2[now][temp]=a2[now][x]+a1[i].w;
 57         dfs(x,temp,now);
 58     }
 59 }
 60 
 61 void out11()
 62 {
 63     printf("\n\n");
 64     for(int i=1;i<=n;++i)
 65       printf("%d ",qian[i]);
 66     printf("\n\n");
 67     for(int i=1;i<=n;++i)
 68       printf("%d ",d[i]);
 69     printf("\n\n");
 70     for(int i=1;i<=n;++i)
 71     {
 72         for(int j=1;j<=n;++j)
 73           printf("%d ",a[i][j]);
 74         printf("\n");
 75     }
 76     printf("\n");
 77     for(int i=1;i<=n;++i)
 78     {
 79         for(int j=1;j<=n;++j)
 80           printf("%lld ",a2[i][j]);
 81         printf("\n");
 82     }
 83     printf("\n");
 84 }
 85 
 86 int main(){
 87     //freopen("1.txt","r",stdin);
 88     //freopen("treas1.in","r",stdin);
 89     //freopen("treas.out","w",stdout);
 90     T=read();
 91     while(T--)
 92     {
 93         int wrong=0;
 94         scanf("%d",&n);
 95         for(int i=1;i<=n;++i)
 96           for(int j=1;j<=n;++j)
 97             scanf("%lld",&a[i][j]);
 98             //a[i][j]=read();
 99         
100         for(int i=1;i<=n;++i)
101           if(a[i][i])wrong=1;
102         
103         for(int i=1;i<=n;++i)
104           for(int j=i+1;j<=n;++j)
105             if(a[i][j]!=a[j][i])
106               wrong=1;
107         
108         if(wrong)
109         {printf("No\n");continue;}
110         
111         clear();
112         
113         d[1]=0;
114         
115         for(int i=1;i<=n;++i)
116         {
117             int k=0;
118             for(int j=1;j<=n;++j)
119               if(!vis[j]&&d[j]<d[k])
120                 k=j;
121             
122             //printf("k=%d\n",k);
123             
124             vis[k]=1;
125             for(int j=1;j<=n;++j)
126               if(!vis[j]&&a[k][j]<d[j])
127               {
128                     //printf("j=%d\n",j);
129                     qian[j]=k;
130                 d[j]=a[k][j];
131                 }
132         }
133         
134         for(int i=2;i<=n;++i)
135           addbian(i,qian[i],d[i]),addbian(qian[i],i,d[i]);
136         
137         for(int i=1;i<=n;++i)
138             dfs(-1,i,i);
139         
140         //out11();
141         
142         for(int i=1;i<=n;++i)
143         {
144             if(wrong==1)break;
145           for(int j=1;j<=n;++j)
146             if(a[i][j]!=a2[i][j])
147             {wrong=1;break;}
148         }
149         
150         if(wrong)
151         {printf("No\n");continue;}
152         
153         dd maxl=0;
154         int order;
155         for(int i=1;i<=n;++i)
156         {
157             dd sum=0;int ci=0;
158             for(int j=first[i];j!=-1;j=a1[j].next)
159             {sum+=a1[j].w;++ci;}
160             sum/=(dd)ci;
161             //printf("i=%d sum=%.4lf\n",i,sum);
162             if(sum>maxl){maxl=sum;order=i;}
163         }
164         
165         
166         printf("Yes\n%d\n",order);
167     }
168     //while(1);
169     return 0;
170 }
code

 































以上是关于藏宝图的主要内容,如果未能解决你的问题,请参考以下文章

藏宝图

藏宝图题解

藏宝图

[NowCoder] 藏宝图

[遇见时光]内推笔试-藏宝图-java实现

BZOJ1560JSOI2009火星藏宝图 [DP]