BZOJ 2657 ZJOI 2012 旅游(journey) 树的直径

题目大意:给出一个凸多边形的三角剖分图,每一个三角形代表一个城市,现在连接这个图中的两个点,问最多能够经过多少个城市。


思路:浙江都是一帮神么。。

这题给的条件简直是不知所云啊。。转化十分巧妙。因为每个凸n边形经过三角剖分之后会出现n - 2个三角形,任意一条边只会成为两个城市的公共边或者整个多边形的边。不难推出两个城市的公共边是n - 3条,也就是说把公共边看成是新图的边的话,就会新图就会构成一颗树。之后就是很水的树的直径了。。。


CODE:

#include <map>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 200010
using namespace std;
#define max(a,b) ((a) > (b) ? (a):(b))
#define min(a,b) ((a) < (b) ? (a):(b))
 
int points;
map<pair<int,int>,int> G;
 
int head[MAX],total;
int next[MAX << 1],aim[MAX << 1];
 
inline void Add(int x,int y)
{
    next[++total] = head[x];
    aim[total] = y;
    head[x] = total;
}
 
int f[MAX];
 
void BFS(int start)
{
    static bool v[MAX];
    memset(v,false,sizeof(v));
    memset(f,0x3f,sizeof(f));
    static queue<int> q;
    while(!q.empty())   q.pop();
    q.push(start);
    f[start] = 0;
    while(!q.empty()) {
        int x = q.front(); q.pop();
        v[x] = true;
        for(int i = head[x]; i; i = next[i]) {
            if(v[aim[i]])   continue;
            f[aim[i]] = f[x] + 1;
            q.push(aim[i]);
        }
    }
}
 
int main()
{
    cin >> points;
    for(int x,y,z,i = 1; i <= points - 2; ++i) {
        scanf("%d%d%d",&x,&y,&z);
        pair<int,int> e(min(x,y),max(x,y));
        if(G.find(e) == G.end())
            G[e] = i;
        else {
            Add(i,G[e]);
            Add(G[e],i);
        }
        e = make_pair(min(y,z),max(y,z));
        if(G.find(e) == G.end())
            G[e] = i;
        else {
            Add(i,G[e]);
            Add(G[e],i);
        }
        e = make_pair(min(x,z),max(x,z));
        if(G.find(e) == G.end())
            G[e] = i;
        else {
            Add(i,G[e]);
            Add(G[e],i);
        }
    }
    BFS(1);
    int p = 0;
    f[0] = 0;
    for(int i = 1; i <= points - 2; ++i)
        if(f[i] > f[p])
            p = i;
    BFS(p);
    cout << *max_element(f + 1,f + points - 1) + 1 << endl;
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值