Topcoder SRM 635 div2 1000

思路:对于输入的 X-Y 边,考虑将该边除去之后形成两棵子树,分别以 X ,Y 为root寻找树的直径(树的两个结点之间的最远长度),这里命名为d1和d2,然后加上 X-Y 边的长度(权值)cost[x][y],每次输入都进行一次运算,并比较,找到最大值即为结果。这里求树的直径可以参考我的关于SPOJ 1437 Longest path in a tree上面的思路及其证明。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
using namespace std;

#define pb push_back
#define fi first
#define se second
#define mk make_pair
#define pil pair<int, ll>
#define rep(i, a, b) for(int i = a; i < b; ++i)
typedef long long ll;
const int maxn = 2020;
bool vis[maxn];
int cost[maxn][maxn];
vector<int>ve[maxn];
int n;
ll ans;
struct Node{
    int v;
    int dis;
    Node(){}
    Node(int v, int dis):v(v),dis(dis){}
};
int bfs(int root, int x, int y){
    memset(vis,0,sizeof(vis));
    ll maxt = 0;
    int maxnode = 0;
    int cnt = root;
    queue<pil>que;
    que.push(pil(root, 0));
    vis[root] = 1;
    while(!que.empty()){
        pil c = que.front();
        que.pop();
        vis[c.fi] = 1;
        int s = ve[c.fi].size();
        for(int i = 0; i < s; ++i){
            int t = ve[c.fi][i];
            if(!vis[t]){
                if(c.fi==x&&t==y||(c.fi==y&&t==x))continue;
                vis[t] = 1;
                que.push(pil(t,c.se+cost[c.fi][t]));
                if(maxt<c.se+cost[c.fi][t]){
                    maxt = c.se + cost[c.fi][t];
                    maxnode = t;
                }
            }
        }
    }
    ans = max(maxt, ans);
    return maxnode;
}
ll work(int root, int x, int y){
    ans = 0;
    int cnt = bfs(root, x, y);
    cnt = bfs(cnt, x, y);
    return ans;
}
void build(vector<int> A, vector<int> B, vector<int> L){
    int s = A.size();
    rep(i,0,maxn)ve[i].clear();///要注意清理干净
    rep(i,0,s){
        int x = A[i];
        int y = B[i];
        ll c = (ll)L[i];
        x++;y++;
        ve[x].pb(y);ve[y].pb(x);
        cost[x][y] = cost[y][x] = c;
    }
}
class LonglongestPathTree {
public:
    long long getLength(vector<int> A, vector<int> B, vector<int> L) {
        n=A.size();
        build(A,B,L);
        ll best = 0;
        rep(i,0,n){
            int x = A[i];
            int y = B[i];
            x++; y++;
            ll d1 = work(x, x, y);
            ll d2 = work(y, x, y);
            best = max(best, d1 + d2 + cost[x][y]);
        }
        return best;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值