1. 程式人生 > >拓補排序+樹的直徑

拓補排序+樹的直徑

訓練題目網址(密碼hpuacm2017): https://vjudge.net/contest/244053

記好下面的模板

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000+10;

int ma[MAXN][MAXN];
int vis[MAXN];
int n, m;
void topo_sort()
{
    for( int i=1; i<=n; i++ )   // 因為有n個頂點一定要迴圈n次
    {
        for( int j=1; j<=n; j++ )   // 每次從頭開始找入度為0的頂點
        {
            if( vis[j] == 0 )
            {
                vis[j]--;   // 刪除的點標記為-1
                printf("%d", j);
                if( i != n )
                    printf(" ");
                else
                    printf("\n");
                for( int k=1; k<=n; k++ )   // 然後找與該頂點相連的頂點以及邊
                {
                    if( ma[j][k] == 1 )
                        vis[k] --;
                }
                break;
            }
        }
    }
}

int main()
{
    while( cin >> n >> m )
    {
        int x, y;
        memset(ma, 0, sizeof(ma));
        memset(vis, 0, sizeof(vis));
        for( int i=1; i<=m; i++ )
        {
            scanf("%d%d", &x, &y);
            if( ma[x][y] != 1 )
            {
                ma[x][y] = 1;
                vis[y]++;
            }
        }
        topo_sort();
    }

    return 0;
}

樹中距離最大的兩個結點之間的距離稱為樹的直徑。

也是好模板

//#include <bits/stdc++.h>
#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
using namespace std;
const int MAXN = 10000+10;
int dis[MAXN];      // 儲存起始節點到當前節點的距離
int vis[MAXN];      // 標記節點已經走過
int ans = 0;
vector< pair<int,int> > v[MAXN];

int BFS( int x )
{
    memset(dis, 0, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    queue<int> q;
    q.push(x);
    vis[x] = 1;
    int poi = 0;
    while( !q.empty() )
    {
        int temp = q.front();
        q.pop();
        if( dis[temp] > ans )   // 如果到當前節點的距離大於已知的最長距離
        {
            ans = dis[temp];
            poi = temp;
        }
        pair<int, int> t;
        for( int i=0; i<v[temp].size(); i++ )
        {
            t = v[temp][i];
            if( vis[t.first] == 0 )
            {
                 vis[t.first] = 1;
                 dis[t.first] = dis[temp] + t.second;   // 儲存到下一個節點的距離
                 q.push(t.first);
            }
        }
    }
    return poi;
}
int main()
{
    int a, b, c;    // a到b權值為c的邊
    char ch;
    while( scanf("%d%d%d", &a, &b, &c) != EOF )
    {
        v[a].push_back(make_pair(b,c));
        v[b].push_back(make_pair(a,c));
    }
    ans = 0;
    int point = BFS(6); // 從任意一個節點開始搜尋
    ans = 0;
    BFS(point);
    printf("%d\n", ans);

    return 0;
}

如果是二維的在圖中搜索,改一下就好了

//#include <bits/stdc++.h>
#include <stdio.h>
#include <queue>
#include <iostream>
#include <string.h>
using namespace std;
const int MAXN = 1000+10;

char ma[MAXN][MAXN];    // 存圖
int dis[MAXN][MAXN];    // 儲存距離
int vis[MAXN][MAXN];    // 標記是否走過
int m, n;
int ans;
int d[4][2] = { 1, 0, -1, 0, 0, 1, 0, -1 }; // 方向陣列
inline pair<int,int> BFS(int x, int y)
{
    memset(dis, 0, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    queue< pair<int,int> > q;
    q.push(make_pair(x,y));
    vis[x][y] = 1;
    pair<int,int> point;
    while( !q.empty() )
    {
        pair<int,int> temp;
        temp = q.front();
        q.pop();
        if( dis[temp.first][temp.second] > ans )
        {
            ans = dis[temp.first][temp.second];
            point = temp;
        }
        for( int i=0; i<4; i++ )
        {
            int dx = temp.first + d[i][0];
            int dy = temp.second + d[i][1];
            if( dx >=0 && dx < n && dy >= 0 && dy < m && ma[dx][dy] == '.' && vis[dx][dy] != 1 )
            {
                vis[dx][dy] = 1;
                dis[dx][dy] = dis[temp.first][temp.second] + 1;
                q.push(make_pair(dx,dy));
            }
        }
    }
    return point;
}

int main()
{
    /* 這道題求得是最大的 . 的連通距離 */
    int t;
    scanf("%d", &t);
    while( t-- )
    {
        scanf("%d%d", &m, &n);
        for( int i=0; i<n; i++ )
            scanf("%s", ma[i]);
        pair<int,int> p;
        for( int i=0; i<n; i++ )
        {
            for( int j=0; j<m; j++ )
            {
                if( ma[i][j] == '.' )
                {
                    ans = 0;
                    p = BFS(i, j);
                    goto out;  // 前幾次這裡就只寫了一個break,結果超時,寫一個只終止了內層迴圈
                }
            }
        }
        out:
        ans = 0;
        BFS(p.first, p.second);
        printf("Maximum rope length is %d.\n", ans);
    }

    return 0;
}