zoukankan      html  css  js  c++  java
  • cf Inverse the Problem (最小生成树+DFS)

    题意:

    N个点。N行N列d[i][j]。

    d[i][j]:结点i到结点j的距离。

    问这N个点是否可能是一棵树。是输出YES,否则输出NO。

    思路:

    假设这个完全图是由一棵树得来的,则我们对这个完全图求最小生成树,得到原树。(画个图就明白)

    故我们对完全图求最小生成树,然后用DFS从这棵树上的每个点出发,判断距离是否和矩阵d相同。

    注意:

    用vector存与每个点相连树枝的另一端,否则超时。用了vector也耗了1400多秒,限时2s。

    代码:

    #include <cstdio>
    #include <iostream>
    #include <string.h>
    #include <cstdlib>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #include <cmath>
    #include <map>
    #include <stack>
    using namespace std;
    int const uu[4] = {1,-1,0,0};
    int const vv[4] = {0,0,1,-1};
    typedef long long ll;
    int const maxn = 50005;
    int const inf = 0x3f3f3f3f;
    ll const INF = 0x7fffffffffffffffll;
    double eps = 1e-10;
    double pi = acos(-1.0);
    #define rep(i,s,n) for(int i=(s);i<=(n);++i)
    #define rep2(i,s,n) for(int i=(s);i>=(n);--i)
    #define mem(v,n) memset(v,(n),sizeof(v))
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    struct node{
        int x,y,len;
    };
    int n;
    int d[2005][2005], a[2005][2005];
    int fa[2005];
    node edge[4000005];
    vector<int> graph[2005];
    
    bool cmp(node a,node b){
        return a.len<b.len;
    }
    
    
    int findFa(int x){
        if(fa[x]!=x) fa[x]=findFa(fa[x]);
        return fa[x];
    }
    
    bool dfs(int start,int x,int fa,int weight){
        if(d[start][x]!=weight){
            return false;
        }
        int L=graph[x].size();
        rep(i,0,L-1){
            int v=graph[x][i];
            if(v==fa) continue;
            bool t=dfs(start,v,x,weight+a[x][v]);
            if(!t) return false;
        }
        return true;
    }
    
    int main(){
        scanf("%d",&n);
        rep(i,1,n) rep(j,1,n) scanf("%d",&d[i][j]);
    
        rep(i,1,n) if(d[i][i]!=0){
            printf("NO
    ");
            return 0;
        }
        rep(i,1,n-1) rep(j,i+1,n){
            if(d[i][j]==0 || (d[i][j]!=d[j][i])){
                printf("NO
    ");
                return 0;
            }
        }
    
        int eNum=0;
        mem(a,0);
    
        rep(i,1,n-1) rep(j,i+1,n){
            edge[++eNum].x=i, edge[eNum].y=j;
            edge[eNum].len=d[i][j];
        }
        sort(edge+1,edge+1+eNum,cmp);
        rep(i,1,n) fa[i]=i;
        rep(i,1,n) graph[i].clear();
    
        rep(i,1,eNum){
            int xx=edge[i].x, yy=edge[i].y;
            int fx=findFa(xx), fy=findFa(yy);
            if(fx!=fy){
                fa[fx]=fy;
                a[xx][yy]=a[yy][xx]=edge[i].len;
                graph[xx].push_back(yy);
                graph[yy].push_back(xx);
            }
        }
    
        int t=findFa(1);
        rep(i,2,n) if(findFa(i)!=t){
            printf("NO
    ");
            return 0;
        }
    
        rep(i,1,n){
            bool k=dfs(i,i,-1,0); //从顶点i出发
            if(!k){
                printf("NO
    ");
                return 0;
            }
        }
        printf("YES
    ");
    }
  • 相关阅读:
    【零基础】极星量化入门九:找到boll的最优回测参数
    【零基础】极星量化入门八:简单的boll实盘
    【零基础】极星量化入门七:简单的boll回测
    解决element-ui中el-menu组件作为vue-router模式在刷新页面后default-active属性与当前路由页面不一致问题的方法
    vue+elementui selet框组件封装 传值
    b模块 小结
    移动端最简单的适配
    判断移动机型字符串
    前端记录cookie 点赞只能点一次
    用chrome预览微信浏览器访问需要OAuth2.0网页授权的页面 适合 微信朋友圈小游戏 HTML5小游戏 微信游戏网页
  • 原文地址:https://www.cnblogs.com/fish7/p/4001253.html
Copyright © 2011-2022 走看看