【NOIP模拟赛】藏宝图 最小生成树

性质:我们把最小生成树建出来,如果其距离符合那么就是对的,不符合就是错的

因为这是个n^2的图所以不能Kruskal只能Prim

#include <cstdio>
#include <cstring>
#include <iostream>
#define N 2500
#define R register
using namespace std;
typedef double DO;
inline long long read()
{
    long long sum=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')
    {
        sum=(sum<<1)+(sum<<3)+ch-'0';
        ch=getchar();
    }
    return sum;
}
struct V
{
    long long to,next,w;
}c[N<<1];
long long head[N+10],t;
long long dis[N+10][N+10],get[N+10][N+10];
DO Ans[N+10];
bool v[N+10];
long long T,n;
long long Dis[N+10],Min;
long long ans;
inline void add(long long x,long long y,long long z)
{
    c[++t].to=y;
    c[t].next=head[x];
    c[t].w=z;
    head[x]=t;
}
inline long long Prim()
{
    memset(head,0,sizeof(head));
    memset(v,0,sizeof(v));
    memset(Dis,0,sizeof(Dis));
    Dis[1]=1;
    t=0;
    Min=0;
    R long long B=n;
    while(B--)
    {
        for(R long long i=1;i<=n;i++)
            if(v[i]==0&&dis[Dis[i]][i]<dis[Dis[Min]][Min])
                Min=i;
        v[Min]=1;
        if(Min!=1)
        {
            add(Dis[Min],Min,dis[Dis[Min]][Min]);
            add(Min,Dis[Min],dis[Dis[Min]][Min]);
        }
        for(R long long i=1;i<=n;i++)
            if(v[i]==0&&dis[Dis[i]][i]>dis[Min][i])
                Dis[i]=Min;
        Min=0;
    }
}
void dfs(long long x,long long r,long long fa,long long D)
{
    get[r][x]=D;
    for(R long long i=head[x];i;i=c[i].next)
    if(c[i].to!=fa)
        dfs(c[i].to,r,x,D+c[i].w);
}
inline bool Go_Die()
{
    for(R long long i=1;i<=n;i++)
        dfs(i,i,0,0);
    for(R long long i=1;i<=n;i++)
        for(R long long j=1;j<=n;j++)
            if(get[i][j]!=dis[i][j])
                return 1;
    return 0;
}
void Dfs(long long x,long long fa)
{
    R long long TT=0;
    for(R long long i=head[x];i;i=c[i].next)
    {
        ++TT;
        Ans[x]+=c[i].w;
        if(c[i].to!=fa)
            Dfs(c[i].to,x);
    }
    Ans[x]/=TT;
    if(Ans[x]>Ans[ans])ans=x;
}
int main()
{
    T=read();
    Ans[0]=-1.0;
    for(R int i=0;i<N+10;i++)dis[0][i]=100000000000000LL;
    while(T--)
    {
        n=read();
        ans=0;
        for(R long long i=1;i<=n;i++)
            for(R long long j=1;j<=n;j++)
                dis[i][j]=read();
        if(n==1)
        {
            printf("Yes\n1\n");
            continue;
        }
        Prim();
        if(Go_Die())printf("No\n");
        else
        {
            for(R long long i=1;i<=n;i++)Ans[i]=0.0;
            Dfs(1,0);
            printf("Yes\n");
            printf("%d\n",ans);
        }
    }
}

 

posted @ 2017-07-30 20:39  TS_Hugh  阅读(225)  评论(0编辑  收藏  举报