zoukankan      html  css  js  c++  java
  • 树的直径(题目)

    A.POJ_2631

     1 #include<iostream>
     2 #include<cstring>
     3 #include<queue>
     4 #include<vector>
     5 using namespace std;
     6 const int maxn = 24000;
     7 int vis[maxn];//把走过的点进行标记
     8 int dis[maxn];//到达每个点所需要走的路径长度。
     9 
    10 vector<pair<int, int> >A[maxn];
    11 long long ans = 0;;
    12 int point = 0;
    13 void bfs(int x)
    14 {
    15     memset(vis, 0, sizeof(vis));
    16     memset(dis, 0, sizeof(dis));
    17     queue<int> que;
    18     que.push(x);
    19     vis[x] = 1;
    20     while (!que.empty()){
    21         int f = que.front();
    22         que.pop();
    23         if (dis[f] > ans){
    24             ans = dis[f];
    25             point = f;
    26         }
    27         pair<int, int> p;
    28         for (int i = 0; i < A[f].size(); i++){ //开始搜索以f为起点的所有的pair
    29             p = A[f][i];                 //这一行是不是更能证明A[x][y]这个二维数组指向的就是一个pair;
    30             if (vis[p.first] == 0){          //如果这个点没有走过则接着走。
    31                 vis[p.first] = 1;           //标记这个点。
    32                 dis[p.first] = dis[f] + p.second;//p.first代表一条边的中点,p.second代表这条边的权值。
    33                 que.push(p.first);
    34             }
    35         }
    36 
    37     }
    38 }
    39 int main()
    40 {
    41     int a, b, c;
    42     while(cin >> a >> b >> c){
    43         A[a].push_back(make_pair(b, c));
    44         A[b].push_back(make_pair(a, c));//建图
    45     }
    46     bfs(1);
    47     ans = 0;
    48     bfs(point);//两次bfs求树的直径
    49     cout << ans << endl;
    50     return 0;
    51 }

    B.POJ_1849

     

     1 #include<iostream>
     2 #include<cstring>
     3 #include<queue>
     4 #include<vector>
     5 using namespace std;
     6 const int maxn = 24000;
     7 int vis[maxn];//把走过的点进行标记
     8 int dis[maxn];//到达每个点所需要走的路径长度。
     9 
    10 vector<pair<int, int> >A[maxn];
    11 long long ans = 0;;
    12 int point = 0;
    13 void bfs(int x)
    14 {
    15     memset(vis, 0, sizeof(vis));
    16     memset(dis, 0, sizeof(dis));
    17     queue<int> que;
    18     que.push(x);
    19     vis[x] = 1;
    20     while (!que.empty()){
    21         int f = que.front();
    22         que.pop();
    23         if (dis[f] > ans){
    24             ans = dis[f];
    25             point = f;
    26         }
    27         pair<int, int> p;
    28         for (int i = 0; i < A[f].size(); i++){ //开始搜索以f为起点的所有的pair
    29             p = A[f][i];                 //这一行是不是更能证明A[x][y]这个二维数组指向的就是一个pair;
    30             if (vis[p.first] == 0){          //如果这个点没有走过则接着走。
    31                 vis[p.first] = 1;           //标记这个点。
    32                 dis[p.first] = dis[f] + p.second;//p.first代表一条边的中点,p.second代表这条边的权值。
    33                 que.push(p.first);
    34             }
    35         }
    36 
    37     }
    38 }
    39 int main()
    40 {
    41     int m, n;
    42     int a, b, c;
    43     int sum = 0;
    44     cin >> m >> n;
    45     for (int i = 0; i < m - 1; i++) {
    46         cin >> a >> b >> c;
    47         A[a].push_back(make_pair(b, c));
    48         A[b].push_back(make_pair(a, c));//建图
    49         sum += c;
    50     }
    51     memset(dis, 0, sizeof(dis));
    52     memset(vis, false, sizeof(vis));
    53     bfs(1);
    54     ans = 0;
    55     bfs(point);//两次bfs求树的直径
    56     cout << 2 * sum - ans << endl;
    57     return 0;
    58 }

    C.找两个人开始相距最大距离除以2即为答案

     1 #include <iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<vector>
     7 #include <iomanip>
     8 
     9 using namespace std;
    10 const int MAN = 10086;
    11 
    12 vector<int>p[MAN];
    13 int dis[MAN];
    14 int vis[MAN];
    15 int n, m, k;
    16 int ans;
    17 
    18 void dfs(int s, int num){
    19     int len = p[s].size();
    20     for (int i = 0; i < len; i++){
    21         if (!vis[p[s][i]]){
    22             vis[p[s][i]] = 1;
    23             if (dis[p[s][i]] == 1)                
    24                 ans = max(ans, num + 1);
    25             dfs(p[s][i], num + 1);
    26             vis[p[s][i]] = 0;
    27         }
    28     }
    29 }
    30 
    31 int main(){
    32     int N;
    33     cin >> N;
    34     while (N--){
    35         memset(dis, 0, sizeof(dis));
    36         memset(vis, 0, sizeof(vis));
    37         cin >> n >> m;
    38         for (int i = 0; i <= n; i++)
    39             p[i].clear();
    40         int s1 = 0, s2 = 0;
    41         k = 0;
    42         for (int i = 0; i < m; i++){
    43             int temp;
    44             cin >> temp;
    45             if (!dis[temp])
    46                 k++;
    47             dis[temp] = 1;
    48             s1 = temp;
    49         }
    50         m = k;
    51         for (int i = 0; i < n - 1; i++){
    52             int a, b;
    53             cin >> a >> b;
    54             p[a].push_back(b);
    55             p[b].push_back(a);
    56         }
    57         if (m == 1){
    58             cout << "0.00" << endl;
    59             continue;
    60         }
    61         queue<int>q;
    62         queue<int>d;
    63         int temp = 1;
    64         q.push(s1);
    65         d.push(0);
    66         vis[s1] = 1;
    67         int maxlen = 0;
    68         while (!q.empty()){
    69             int s = q.front();
    70             int num = d.front();
    71             d.pop();
    72             q.pop();
    73             int len = p[s].size();
    74             for (int i = 0; i < len; i++){
    75                 if (!vis[p[s][i]]) {
    76                     q.push(p[s][i]);
    77                     d.push(num + 1);
    78                     vis[p[s][i]] = 1;
    79                     if (dis[p[s][i]] == 1){
    80                         temp++;
    81                         if (num + 1 > maxlen){
    82                             maxlen = num + 1;
    83                             s2 = p[s][i];
    84                         }
    85                         if (temp == m)
    86                             break;
    87                     }
    88                 }
    89             }
    90         }
    91         ans = 0;
    92         memset(vis, 0, sizeof(vis));
    93         vis[s2] = 1;
    94         dfs(s2, 0);
    95         ans /= 2;
    96         double answer = ans;
    97         cout << fixed << setprecision(2) << answer  << endl;
    98     }
    99 }

    D.树的内核  floyd算法(超时)  考虑用树的直径

    // 超时代码
    //#include<iostream>
    //#include<cstring>
    //#include<algorithm>
    //#define FOR(a,b,c) for(int a=(b);a<(c);a++)	//	利用宏定义函数简化代码
    //
    //using namespace std;
    //
    //const int maxn = 5000;
    //const int INF = 1 << 30;
    //int nodes[maxn], nodes_n;
    //int det[maxn][maxn];
    //int ans, n, S;
    //
    //int main() {
    //	ios::sync_with_stdio(false);	// 提高iostream性能
    //	cin >> n >> S;
    //	FOR(i, 1, n + 1) 
    //		FOR(j, 1, n + 1)
    //			if (i != j) 
    //				det[i][j] = INF;
    //	int u, v, w;
    //	FOR(i, 0, n - 1) {
    //		cin >> u >> v >> w;
    //		det[v][u] = det[u][v] = w;
    //	}
    //	// floyd	算法
    //	FOR(k, 1, n + 1)
    //		FOR(i, 1, n + 1)
    //			FOR(j, 1, n + 1)
    //				if (det[i][k] < INF && det[k][j] < INF)
    //					det[i][j] = min(det[i][j], det[i][k] + det[k][j]);
    //	int _max = 0, maxi, maxj;  //找直径 
    //	FOR(i, 1, n + 1) FOR(j, 1, n + 1)
    //		if (det[i][j]<INF && det[i][j]>_max) {
    //			_max = det[i][j];
    //			maxi = i; maxj = j;
    //		}
    //	ans = INF;
    //	FOR(i, 1, n + 1) 
    //		if (det[maxi][i] + det[maxj][i] == det[maxi][maxj])
    //	FOR(j, 1, n + 1) 
    //		if (det[maxi][j] + det[maxj][j] == det[maxi][maxj]) {
    //		if (det[i][j] > S) 
    //			continue;  //直径上 长度<=S 的一段 
    //		int ecg = max(min(det[i][maxi], det[j][maxi]), min(det[maxj][i], det[maxj][j]));
    //		ans = min(ans, ecg);
    //	}
    //	cout << ans << endl;
    //	return 0;
    //}
    
    //正解
    
    // 两个结论
    //(1)对于树中的任意一点,距离其最远的点一定是树的直径的某一端点。
    //(2)所有的直径是等价的,即任意一条所能求出的该最小偏心距相等。
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    
    using namespace std;
    
    inline const int get() {
    	int x = 0, f = 1;
    	char ch = getchar();
    	while (ch > '9' || ch < '0'){ 
    		if (ch == '-')
    		f = -1; 
    		ch = getchar();
    	}
    	while (ch >= '0'&&ch <= '9') { 
    		x = x * 10 + ch - '0'; 
    		ch = getchar();
    	}
    	return x * f;
    }
    
    const int N = 5e5 + 100;
    int dis[N], f[N];
    bool vis[N];
    vector<pair<int, int> >det[N];
    
    void dfs(int x) {
    	for (int i = 0; i < det[x].size(); i++) {
    		int nx = det[x][i].first;
    		if (vis[nx] || nx == f[x])
    			continue;
    		f[nx] = x;
    		dis[nx] = dis[x] + det[x][i].second;
    		dfs(nx);
    	}
    }
    int main() {
    	int n = get(), s = get();
    	for (int i = 1; i < n; i++) {
    		int u = get(), v = get(), w = get();
    		det[u].push_back(make_pair(v, w));
    		det[v].push_back(make_pair(u, w));
    	}
    	int l = 1, l2 = 1;
    	dis[l] = 0; dfs(l);
    	memset(f, 0, sizeof f);
    	for (int i = 1; i <= n; i++) 
    		if (dis[i] > dis[l]) l = i;
    	dis[l] = 0; dfs(l);
    	for (int i = 1; i <= n; i++) 
    		if (dis[i] > dis[l2]) 
    			l2 = i;
    	int ans = 0x7fffffff, j = l2;
    	for (int i = l2; i; i = f[i]) {
    		while (f[j] && dis[i] - dis[f[j]] <= s) 
    			j = f[j];
    		ans = min(ans, max(dis[j], dis[l2] - dis[i]));
    	}
    	for (int i = l2; i; i = f[i]) 
    		vis[i] = 1;
    	for (int i = l2; i; i = f[i]) 
    		dis[i] = 0, dfs(i);
    	for (int i = 1; i <= n; i++) 
    		ans = max(ans, dis[i]);
    	cout << ans << endl;
    	return 0;
    }
    
    作者:LightAc
    出处:https://www.cnblogs.com/lightac/
    联系:
    Email: dzz@stu.ouc.edu.cn
    QQ: 1171613053
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    小说下载器【追书接口】
    C#调用大漠插件,发送QQ和微信消息
    C# 终本案件、综合执行人、裁判文书爬虫
    追书神器API
    一个CookieContainer的拓展类
    利用BlockingCollection实现生产者和消费者队列,实现写文本
    EF SQLite的Like语句,生成为CHARINDEX的解决办法
    ClientKey实现登录QQ空间,并设置背景音乐
    DataTable转换为Model实体对象
    开通博客第一天!
  • 原文地址:https://www.cnblogs.com/lightac/p/10544087.html
Copyright © 2011-2022 走看看