codeForces 472D 最小生成树
题目大意:给出一个图中点的两两距离,问是否是一棵树,若是,求出平均边权最大的点
prim最小生成树,若原图是树,则最小生成树的距离就是原距离。否则不是。
搞出来树了,第二问随便dfs就好了。
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #define N 2550 using namespace std; int T,n,fa[N],pp[N]; long long dis[N][N],minn[N],a[N][N],ans,num; bool boo; double maxn; int final; int head[N],e=1; struct edge{ int u,v,w,next; }ed[2*N]; void add(int u,int v,int w){ ed[e].u=u; ed[e].v=v; ed[e].w=w; ed[e].next=head[u]; head[u]=e++; } bool bo[N]; void dfs(int x,int now,long long d){ if(bo[now])return; bo[now]=1; dis[x][now]=d; for(int i=head[now];i;i=ed[i].next) dfs(x,ed[i].v,d+ed[i].w); } int main() { //freopen("treas.in","r",stdin); //freopen("treas.out","w",stdout); scanf("%d",&T); while(T--){ memset(head,0,sizeof head); e=1; memset(bo,0,sizeof bo); memset(minn,0x7f,sizeof minn); scanf("%d",&n); boo=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lld",&a[i][j]); for(int i=1;i<=n;i++){ minn[i]=a[1][i]; pp[i]=1; } bo[1]=1; fa[1]=0; for(int i=1;i<n;i++) { int now=0; for(int j=1;j<=n;j++) if(!bo[j]&&minn[j]<minn[now]) now=j; bo[now]=1; fa[now]=pp[now]; add(pp[now],now,a[pp[now]][now]); add(now,pp[now],a[now][pp[now]]); for(int j=1;j<=n;j++) if(!bo[j]&&a[now][j]<minn[j]){ minn[j]=a[now][j]; pp[j]=now; } } //for(int i=1;i<=n;i++) //printf("%d %d\n",i,fa[i]); for(int i=1;i<=n;i++){ memset(bo,0,sizeof(bo)); dfs(i,i,0); } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ //printf("%lld ",dis[i][j]); if(a[i][j]!=dis[i][j]){ boo=1; break; } }if(boo==1) break; //printf("\n"); }if(boo==1){printf("No\n"); continue;} maxn=0; final=1; for(int i=1;i<=n;i++){ num=ans=0; for(int j=head[i];j;j=ed[j].next){ num++; ans+=ed[j].w; } if((double)(1.0*ans)/(1.0*num)>maxn){ final=i; maxn=(double)(1.0*ans)/(1.0*num); } } printf("Yes\n%d\n",final); } }
人生如梦亦如幻 朝如晨露暮如霞。