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);
    }
}


posted @ 2017-07-28 21:43  Ren_Ivan  阅读(389)  评论(0编辑  收藏  举报