码迷,mamicode.com
首页 > 其他好文 > 详细

藏宝图

时间:2017-07-28 20:59:51      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:++   stdout   题目   names   生成   char   接下来   scanf   mem   

背景
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

 

藏宝图

标签:++   stdout   题目   names   生成   char   接下来   scanf   mem   

原文地址:http://www.cnblogs.com/A-LEAF/p/7252424.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!