hihocoder 1192 簡單的樹嵌入 (樹上DFS 構造 好題)

_TCgogogo_發表於2015-07-28


#1192 : 簡單的樹嵌入

時間限制:10000ms
單點時限:1000ms
記憶體限制:256MB

描述

給定一棵n個點的無權樹。定義兩點i, j(0 ≤ i, j ≤ n - 1)間的距離d(i, j)為兩點間樹上最短路徑的長度(邊數)。

我們需要將這n個點對映到中的向量v0 = (v0, 0, ..., v0, m - 1), ..., vn - 1 = (vn - 1, 0, ..., vn - 1, m - 1)。定義兩向量vi, vj間的L1距離為


我們希望對於所有0 ≤ i, j ≤ n - 1有d(i, j) = d1(vi, vj)。

輸入

第一行n。下面n - 1行,其中第i行為兩個空格分開的整數xi, yi,表示點xi和yi間有一條邊。

n ≤ 100. 0 ≤ xi, yi ≤ n - 1.

輸出

第一行m。下面n行,其中第i行為m個空格分開的整數vi - 1, 0, ..., vi - 1, m - 1

要求m ≤ 100且 - 100 ≤ vi, j ≤ 100。並且,對於所有0 ≤ i, j ≤ n - 1,d(i, j) = d1(vi, vj)。

如果有多解,輸出任意一組滿足要求的解即可。

樣例輸入

3

0 1

1 2

樣例輸出

2

0 0

0 1

1 1

題目連結:http://hihocoder.com/problemset/problem/1192

題目大意:給出一棵樹,要求構造一個矩陣,如果第i個點到第j個點的距離為d(i,j),則矩陣的第i行和第j行對應列的差的絕對值的和要等於d(i,j)

題目分析:構造方法太多,我就寫一下我的構造方法,感覺是最簡單的,直接構造一個n*n的矩陣,對於第i個點,先將其父親那一行復制過來然後再將(i,i)點標記為1即可,其實就相當於用1的個數給樹分層


#include <cstdio>
#include <cstring>
int const MAX = 105;

struct EDGE
{
    int v, next;
}e[MAX];
int head[MAX], cnt;
int ans[MAX][MAX];

void Add(int u, int v)
{
    e[cnt].v = v;
    e[cnt].next = head[u];
    head[u] = cnt ++;
}

void DFS(int u, int fa)
{
    memcpy(ans[u], ans[fa], sizeof(ans[fa]));
    ans[u][u] = 1;
    for(int i = head[u]; i != -1; i = e[i].next)
    {
        int v = e[i].v;
        if(v != fa)
            DFS(v, u);
    }
    return;
}   

int main()
{
    int n;
    scanf("%d", &n);
    memset(ans, 0, sizeof(ans));
    memset(head, -1, sizeof(head));
    for(int i = 0; i < n - 1; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        Add(u, v);
        Add(v, u);
    }
    DFS(0, 0);
    printf("%d\n", n);
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n - 1; j++)
            printf("%d ", ans[i][j]);
        printf("%d\n", ans[i][n - 1]);
    }
}

相關文章