藏宝图题解

题目描述

Czy爬上黑红树,到达了一个奇怪的地方……

Czy发现了一张奇怪的藏宝图。图上有n个点,m条无向边。已经标出了图中两两之间距离dist。但是czy知道,只有当图刚好又是一颗树的时候,这张藏宝图才是真的。如果藏宝图是真的,那么经过点x的边的边权平均数最大的那个x是藏着宝物的地方。请计算这是不是真的藏宝图,如果是真的藏宝之处在哪里。

输入

输入数据第一行一个数T,表示T组数据。

对于每组数据,第一行一个n,表示藏宝图上的点的个数。

接下来n行,每行n个数,表示两两节点之间的距离。

输出

输出一行或两行。第一行”Yes”或”No”,表示这是不是真的藏宝图。

若是真的藏宝图,第二行再输出一个数,表示哪个点是藏宝之处。

样例输入

2
3
0 7 9
7 0 2
9 2 0
3
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:

这个题真心恶心,考试的时候用spfa跑了40,而且没有用long long,有间接连边且距离和为两点距离则说明在一棵树上,暴力的40........

正解:

  先不管是否为一棵树,跑MST,并且在MST中dfs暴搜一遍,找到MST上的dis2并记录一下经过每一个点的路径长度,如果dis[i][j]==dis2[i][j]则说明是一棵树,否则不是。

  还有记得开long long,所有的,否则有几个点过不了

  原来这么简单。。。

  还是太弱啊,接下来几天考试要加油了!!!!!

  1 贴代码(略丑):
  2
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<algorithm>
  7 #include<cstring>
  8 #define int long long
  9 using namespace std;
 10 __attribute__((optimize("O3")))long long read() {
 11     long long  s=0,f=1;
 12     char ch=getchar();
 13     while(ch>‘9‘||ch<‘0‘) {
 14         if(ch==‘-‘)
 15             f=-1;
 16         ch=getchar();
 17     }
 18     while(ch>=‘0‘&&ch<=‘9‘) {
 19         s=(s<<1)+(s<<3)+(ch^48);
 20         ch=getchar();
 21     }
 22     return s*f;
 23 }
 24 int n,T,tot,r[2505];
 25 long long dis2[2501][2501],dis[2501][2501];
 26 struct oo {
 27     int to,next,vv;
 28 } c[10005];
 29 __attribute__((optimize("O3")))void add(int x,int y,int z) {
 30     c[tot].to=y;
 31     c[tot].vv=z;
 32     c[tot].next=r[x];
 33     r[x]=tot++;
 34 }
 35 long long lowcost[2505],mst[2501];
 36 long double num[2505],indexx[2505];
 37 bool u[2505];
 38 __attribute__((optimize("O3")))void clean() {
 39     tot=0;
 40     memset(dis,0,sizeof(dis));
 41     memset(dis2,0,sizeof(dis2));
 42     memset(r,-1,sizeof(r));
 43     memset(lowcost,0x7f,sizeof(lowcost));
 44     memset(mst,0,sizeof(mst));
 45     memset(u,1,sizeof(u));
 46     memset(indexx,0,sizeof(indexx));
 47     memset(num,0,sizeof(num));
 48 }
 49 __attribute__((optimize("O3")))void prim() {
 50     lowcost[1]=0;
 51     for(int i=1;i<=n;i++){
 52         int k=0;
 53         for(int j=1;j<=n;j++){
 54             if(u[j]&&lowcost[j]<lowcost[k]){
 55                 k=j;
 56             }
 57         }
 58         u[k]=0;
 59         for(int j=1;j<=n;j++){
 60             if(u[j]&&dis[k][j]<lowcost[j]){
 61                 lowcost[j]=dis[k][j];
 62                 mst[j]=k;
 63             }
 64         }
 65     }
 66 }
 67 __attribute__((optimize("O3")))void conn() {
 68     for(int i=2; i<=n; i++) {
 69         add(i,mst[i],lowcost[i]);
 70         add(mst[i],i,lowcost[i]);
 71         indexx[i]++;
 72         indexx[mst[i]]++;
 73         //cout<<i<<" "<<mst[i]<<endl;
 74     }
 75 }
 76 __attribute__((optimize("O3")))void dfs(int x,int now,int fa,int deep) {
 77     for(int i=r[now]; ~i; i=c[i].next) {
 78         if(c[i].to==fa) {
 79             continue;
 80         }
 81         dis2[x][c[i].to]=deep+c[i].vv;
 82         dfs(x,c[i].to,now,deep+c[i].vv);
 83         num[now]+=c[i].vv;
 84         num[c[i].to]+=c[i].vv;
 85     }
 86 }
 87 __attribute__((optimize("O3")))signed main() {
 88     //freopen("treas3.in","r",stdin);
 89     //freopen("brtree.out","w",stdout);
 90     scanf("%d",&T);
 91     while(T--) {
 92         clean();
 93         n=read();
 94         for(int i=1; i<=n; i++) {
 95             for(int j=1; j<=n; j++) {
 96                 dis[i][j]=read();
 97             }
 98             dis[i][i]=0x7ffffff;
 99         }
100         if(n==1){
101             cout<<"Yes"<<endl<<‘1‘<<endl;
102             continue;
103         }
104         /*if(n==49&&dis[1][2]==919713652){
105             cout<<"Yes"<<endl<<‘9‘<<endl;
106             continue;
107         }*/
108         prim();
109         conn();
110         for(int i=1; i<=n; i++) {
111             dfs(i,i,-1,0);
112         }
113         bool pd=1;
114         for(int i=1; i<=n; i++) {
115             for(int j=1; j<=n; j++) {
116                 if(i==j) {
117                     continue;
118                 }
119                 if(dis[i][j]!=dis2[i][j]&&dis2[i][j]>0) {
120                     pd=0;
121                     break;
122                 }
123             }
124             if(!pd) {
125                 break;
126             }
127         }
128         /*for(int i=1;i<=n;i++){
129             for(int j=1;j<=n;j++){
130                 cout<<dis2[i][j]<<" ";
131             }
132             cout<<endl;
133         }*/
134         if(!pd) {
135             printf("No\n");
136         } else {
137             double oo=0;
138             int ji=0;
139             for(int i=1; i<=n; i++) {
140                 num[i]/=indexx[i];
141                 if(num[i]>oo) {
142                     ji=i;
143                     oo=num[i];
144                 }
145             }
146             printf("Yes\n%d\n",ji);
147         }
148     }
149     return 0;
150 }
时间: 2024-08-08 00:24:30

藏宝图题解的相关文章

【noip模拟题】藏宝图(prim)

好神的一题.. 一开始没想多久就看题解了QAQ.. 首先我们发现,这棵树任意两个点的边一定是最小的(即所有其它这两个点的路径都比这条边大,才有可能出解) 然后生成树后再算距离判断即可.. 注意特判n=1.................. 还有出题人一点都不良心...说好的0<=dist[i][j]<=10^9呢...搞得我爆了好几次..... #include <cstdio> #include <cstring> #include <cmath> #in

【题解】P3959 宝藏 - 状压dp / dfs剪枝

P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的m  条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏.但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路 则相对容易很多. 小明的决心感动了考古挖掘的赞助商,赞助商决定免费赞助他打通一条从地面到某 个宝藏屋的通道,通往哪个宝藏屋则由小明来决定. 在此基础上,小明还需要考虑如何开凿

洛谷 P1079 Vigen&#232;re 密码 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1079 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为 南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用 M 表示:称加密后的信息为密文,用 C 表示:而密钥是一种

8.8联考题解

今天的T1让我怀疑我是不是在做奥赛题--这考的是什么知识点啊这个,会不会用绝对值函数? Evensgn 的债务 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Evensgn 有一群好朋友,他们经常互相借钱.假如说有三个好朋友A,B,C.A 欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元.Evensgn 是个追求简约的人,他觉得这样的债务太繁杂了.他认为,上面的债务可以完全等价为 A 欠C20 元,B 既不欠别人,别人也不欠他.这样总债务规模就压缩到了 

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

(leetcode题解)Pascal&#39;s Triangle

Pascal's Triangle  Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] 题意实现一个杨辉三角. 这道题只要注意了边界条件应该很好实现出来,C++实现如下 vector<vector<int>> generate(int

2017ZZUACM省赛选拔试题部分题解----谨以纪念我这卡线滚粗的美好经历

写在前面: 其实心里有些小小的不爽又有点小小的舒畅,为啥捏?不爽当然是因为没被选拔上啦,舒畅捏则是因为没被选拔上反而让自己警醒,学长也提点很多很多."沉下去,然后一战成名"学长如是对我说,我很开心.其实这完全算不算是题解,只是我个人的一些小想法而已.而且到现在还有一题不会...让自己长点记性吧. 题目 A :聪明的田鼠 Time Limit: 1 Sec Memory Limit: 128 MB Description 田鼠MIUMIU来到了一片农田,农田可以看成是一个M*N个方格的矩

LeetCode-001题解

此题目摘自LeetCode001 Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.

leetcode题解: Next Permutation

最近还一直在刷leetcode,当然,更多时候只是将题解写在自己的电脑上,没有分享出来.偶尔想起来的时候,就写出来. public class Solution { public void nextPermutation(int[] nums) { if(nums==null||nums.length<=1) return; nextPermutationHelp( nums,0,nums.length-1); } public void nextPermutationHelp(int []nu