zoukankan      html  css  js  c++  java
  • prim+dfs 藏宝图

      

    问题 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

           首先要判断是不是一棵树,用最小生成树,然后深搜(spfa太慢,但是O(能过))出每两点间的距离。

     判断与原来矩阵是否完全相同。是则为一棵树。

          最小生成树只能用prim,边太多,klus会卡崩。

            ll k=0;
            for(ll j=1;j<=n;j++)
               if(vis[j]&&dis[j]<dis[k])
                  k=j;
            vis[k]=0;
            for(ll j=1;j<=n;j++)
               if(vis[j]&&a[k][j]<dis[j])
                   dis[j]=a[k][j],to[j]=k;
        }
        for(ll i=1;i<=n;i++)
        { 
            add(i,to[i],dis[i]);
            add(to[i],i,dis[i]);
            c[i][to[i]]=dis[i];
            c[to[i]][i]=dis[i];
        }
        //for(ll i=1;i<=e;++i)
          //cout<<lu[i].u<<" "<<lu[i].v<<endl;
    }
    void dfs(ll x,ll y,ll root)
    {
        //vis[x]=1;
        for(ll i=adj[x];i!=-1;i=lu[i].next)
           if(lu[i].v!=y)
           {
                b[root][lu[i].v]=b[root][x]+lu[i].l;
                dfs(lu[i].v,x,root);
           }
    }
    int main()
    {
        //freopen("treas.in","r",stdin);
        //freopen("treas.out","w",stdout);
        t=read();
        while(t--)
        {
            p=0;e=0;
            memset(adj,-1,sizeof(adj));
            memset(c,0,sizeof(c));
            memset(b,0,sizeof(b));
            prim();
            for(int i=1;i<=n;i++)
            {
                memset(vis,0,sizeof(vis));  
                dfs(i,i,i);
            }
            for(ll i=1;i<=n;i++)
            {
               for(ll j=1;j<=n;j++)
                   if(a[i][j]!=b[i][j])
                    {
                        printf("No
    ");
                        p=1;
                        break;
                    }
                if(p==1)break;  
            }
            if(p==1)continue;
            ll s=-1,tt=0;
            for(ll i=1;i<=n;i++)
            {
                ll k=0,y=0;
                for(ll j=1;j<=n;j++)
                  if(c[i][j])
                    k+=c[i][j],y++;
                if(y!=0)k/=y;
                if(k>s)s=k,tt=i;
            }
            printf("Yes
    %d
    ",tt);
        }
    }



  • 相关阅读:
    c++ 连接mysql数据库
    c语言数据结构分析2之 链表插入删除
    c语言数据结构分析1之 链表创建
    微软 翻译工具
    c语言数据结构分析7之 二分查找
    sencha touch2 demo
    程序员装B指南
    c语言数据结构分析6之 快速排序
    c语言数据结构分析5之 冒泡
    对话jQuery之父John Resig:JavaScript的开发之路
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632768.html
Copyright © 2011-2022 走看看