题目大意:给出一个凸多边形的三角剖分图,每一个三角形代表一个城市,现在连接这个图中的两个点,问最多能够经过多少个城市。
思路:浙江都是一帮神么。。
这题给的条件简直是不知所云啊。。转化十分巧妙。因为每个凸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; }
BZOJ 2657 ZJOI 2012 旅游(journey) 树的直径
原文地址:http://blog.csdn.net/jiangyuze831/article/details/41827733