【ZOJ】 3820 Building Fire Stations

来源:互联网 发布:淘宝名龙堂电脑怎么样 编辑:程序博客网 时间:2024/06/06 12:36

贪心可知选取的两点一定在树的直径上。。。先求出直径,然后对直径上的每个点求一下这个点不走直径能到达的最远距离,然后二分答案,判断是否可行即可。。。

#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits>#include <cstdlib>#include <cmath>#include <time.h>#define maxn 200005#define maxm 400005#define eps 1e-10#define mod 1315423911#define INF 1e17#define lowbit(x) (x&(-x))#define mp make_pair#define ls o<<1#define rs o<<1 | 1#define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, Rtypedef long long LL;typedef unsigned long long ULL;//typedef int LL;using namespace std;LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}void scanf(int &__x){__x=0;char __ch=getchar();while(__ch==' '||__ch=='\n')__ch=getchar();while(__ch>='0'&&__ch<='9')__x=__x*10+__ch-'0',__ch = getchar();}LL gcd(LL _a, LL _b){if(!_b) return _a;else return gcd(_b, _a%_b);}// headstruct Edge{int v;Edge *next;}pool[maxm], *H[maxn], *edges;queue<pair<int, int> > q;int flag[maxn], vis[maxn];int po[maxn], most[maxn];int dist[maxn], pre[maxn];int n, cnt, ans1, ans2;void init(void){cnt = 0;edges = pool;memset(H, 0, sizeof H);memset(flag, 0, sizeof flag);}void addedges(int u, int v){edges->v = v;edges->next = H[u];H[u] = edges++;}void read(void){int u, v;scanf("%d", &n);for(int i = 1; i < n; i++) {scanf("%d%d", &u, &v);addedges(u, v);addedges(v, u);}}int bfs(int s){int mx = 0, t = s;memset(vis, 0, sizeof vis);dist[s] = 0, vis[s] = 1, pre[s] = 0;q.push(mp(s, 0));while(!q.empty()) {pair<int, int> pp = q.front();q.pop();int u = pp.first, d = pp.second;if(dist[u] > mx) mx = dist[u], t = u;for(Edge *e = H[u]; e; e = e->next) {int v = e->v;if(!vis[v]) {vis[v] = 1;dist[v] = d + 1;pre[v] = u;q.push(mp(v, dist[v]));}}}return t;}void find(int now){while(now) {po[++cnt] = now;flag[now] = 1;now = pre[now];}}int BFS(int s){int mx = 0;vis[s] = 1, q.push(mp(s, 0));while(!q.empty()) {pair<int, int> pp = q.front();q.pop();int u = pp.first, d = pp.second;mx = max(mx, d);for(Edge *e = H[u]; e; e = e->next) {int v = e->v;if(!vis[v] && !flag[v]) {vis[v] = 1;q.push(mp(v, d+1));}}}return mx;}bool check(int d){int a = 0, b = cnt+1;int tt = 0;for(int i = 1; i <= cnt; i++) {if(tt > d || most[i] > d) break;else a = i, ans1 = po[i], tt += 1;}tt = 0;for(int i = cnt; i >= 1; i--) {if(tt > d || most[i] > d) break;else b = i, ans2 = po[i], tt += 1;}if(ans1 == ans2) ans2 = po[b+1];//printf("a = %d b = %d\n", a, b);if(a >= b) return true;int ok = 1;for(int i = a; i <= b; i++) if(min(i - a + most[i], b - i + most[i]) > d) ok = 0;return ok;}void work(void){int s1, s2;s1 = bfs(1);s2 = bfs(s1);find(s2);//printf("s1 = %d s2 = %d\n", s1, s2);//for(int i = 1; i <= cnt; i++) printf("%d\n", po[i]);memset(vis, 0, sizeof vis);for(int i = 1; i <= cnt; i++) most[i] = BFS(po[i]);//printf("AA %d BB\n", check(2));int bot = 0, top = dist[s2], mid, res;while(top >= bot) {mid = (top + bot) >> 1;if(check(mid)) res = mid, top = mid - 1;else bot = mid + 1;}check(res);printf("%d %d %d\n", res, ans1, ans2);}int main(void){int _;while(scanf("%d", &_)!=EOF) {while(_--) {init();read();work();}}return 0;}


0 0