藏宝图题解
题目描述
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 }