标签:++ 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 }
标签:++ stdout 题目 names 生成 char 接下来 scanf mem
原文地址:http://www.cnblogs.com/A-LEAF/p/7252424.html