藏宝图

来源:互联网 发布:江东陆伯言 知乎 编辑:程序博客网 时间:2024/06/04 19:31

问题 C: 藏宝图

时间限制: 2 Sec  内存限制: 256 MB

题目描述

Czy爬上黑红树,到达了一个奇怪的地方……

Czy发现了一张奇怪的藏宝图。图上有n个点,m条无向边。已经标出了图中两两之间距离dist。但是czy知道,只有当图刚好又是一颗树的时候,这张藏宝图才是真的。如果藏宝图是真的,那么经过点x的边的边权平均数最大的那个x是藏着宝物的地方。请计算这是不是真的藏宝图,如果是真的藏宝之处在哪里。


输入

输入数据第一行一个数T,表示T组数据。

对于每组数据,第一行一个n,表示藏宝图上的点的个数。

接下来n行,每行n个数,表示两两节点之间的距离。

输出

输出一行或两行。第一行”Yes”或”No”,表示这是不是真的藏宝图。

若是真的藏宝图,第二行再输出一个数,表示哪个点是藏宝之处。

样例输入

230 7 97 0 29 2 030 2 72 0 97 9 0

样例输出

Yes1Yes3样例解释:第一棵树的形状是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


最小生成树

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<set>
#include<deque>
#include<cstdlib>
#include<algorithm>
#define V 2505
#define mod 1000000007
#define LL long long
usingnamespacestd;
intn,m,vis[V];
intrt;
LL mx;
LL a[V][V],d[V];
intts;
intf[V],is[V],ans;
LL it[V];
structda
{
  intto,next;      
}Edge[V*5];
inthead[V],tot;
inlinevoidadd(intx,inty)
{
  Edge[tot].to=y;
  Edge[tot].next=head[x];
  head[x]=tot++;      
}
inlinevoiddd()
{
   memset(d,127,sizeof(d));
   d[1]=0;
  while(1)
  {
      rt=0;mx=mod;
      for(inti=1;i<=n;i++)
      if(!vis[i]&&d[i]<mx)
      {
         mx=d[i];
         rt=i;    
      
      if(!rt)break;
      vis[rt]=1;
      for(intj=1;j<=n;j++)
      if(d[j]>a[rt][j]&&!vis[j])
      {
         d[j]=a[rt][j];
         f[j]=rt;   
      }
  }
}
inlinevoidinit()
{
  tot=0;
  memset(head,-1,sizeof(head));
  memset(f,0,sizeof(f));  
  memset(a,0,sizeof(a));
  memset(vis,0,sizeof(vis));
  memset(is,0,sizeof(is));
  memset(it,0,sizeof(it)); 
  ans=0;
}
voiddfs(intx)
{
     intv;
     vis[x]=1;
   for(inti=head[x];i!=-1;i=Edge[i].next)
   {
       v=Edge[i].to;
       if(vis[v])continue;
       d[v]=d[x]+a[x][v];
       dfs(v);        
   }     
}
inlineinthaha()
{
    //freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
   // freopen("treas.in","r",stdin); freopen("treas.out","w",stdout);
    intt;
    cin>>t;
    intxx,yy;
    while(t--)
    {
          init();
          scanf("%d",&n);
          for(inti=1;i<=n;i++)
            for(intj=1;j<=n;j++)
             scanf("%lld",&a[i][j]);
          dd();
         for(inti=1;i<=n;i++)
         {
          if(f[i]==0)continue;
          add(i,f[i]);
          add(f[i],i);
         }
         memset(vis,0,sizeof(vis));
          memset(d,0,sizeof(d));
         dfs(1);
        for(inti=1;i<=n;i++)
        if(d[i]!=a[1][i])
        {
         ans=1;break;                
        
          if(ans)
          {
            printf("No\n");
            continue;      
          }
          if(n==1){printf("Yes\n1\n");continue;}
          for(inti=1;i<=n;i++)
          {
          //cout<<i<<"  "<<f[i]<<endl;
            if(f[i]==0)continue;
            is[f[i]]++;
            is[i]++; 
            it[i]+=a[i][f[i]];
            it[f[i]]+=a[i][f[i]];     
          }
          doublesd=-1;
          intyy=0;
          for(inti=1;i<=n;i++)
          {
            if(double(it[i])/double(is[i])>sd)
            {
              yy=i;
              sd=double(it[i])/double(is[i]);
            }       
          }
          printf("Yes\n%d\n",yy);
          //cout<<i<<" &&"<<f[i]<<" "<<n<<endl;
    }
    return0;
}
intgg=haha();
intmain()
{;}

原创粉丝点击