拓補排序+樹的直徑
阿新 • • 發佈:2019-02-10
訓練題目網址(密碼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; }