[搜索]Sugigma: The Showdown

Description

从前有一只巨大的鹿想喝水,老爷爷为了恢复环境,想阻止这只巨大的鹿喝水。

老爷爷和鹿同在一片草地里。这片草地里一共有N个水池子,鹿会在水池之间移动,而老爷爷则会乘坐德国进口的高科技糹乙万恶木馬,在水池间追赶这头巨大多喝水的鹿。水池之间连了N−1条红色边和N−1条蓝色边,分别构成两棵树。巨大的鹿只会沿着红色边行走,而高科技糹乙万恶木馬只会沿着蓝色边行走。

走一条边是很耗时间的,在每个人走每条边的时间里,巨大多喝水的鹿都会喝掉1吨水(鹿在行走过程中也能喝水,这些水是用即可科技转化空气产生的)。初始时,巨大的鹿位于X号水池,老爷爷位于Y号水池。巨大的鹿和高科技糹乙万恶木馬会轮流行走,鹿先走一步,万恶木馬走第二步,鹿再走第三步,······,以此类推,每一步都会选择最优策略。当然,轮到一个人(或鹿)走的时候,他也可以选择不走,而是坐在原地休息,这段时间里鹿也会喝掉1吨的水,休息完之后就又轮到对方了。当老爷爷和鹿位于同一个水池时,鹿就会被老爷爷深度烧烤,从而再也无法喝水。当然,也可能存在老爷爷永远无法追上鹿的情况,这种时候老爷爷就会伤筋动骨。

巨大的鹿的目标是喝尽可能多的水,而老爷爷的目标是让它喝尽可能少的水。鹿想知道它最多能喝多少水,如果你能帮他算出来,它会带你到饭店换一台手机。

Input

第一行包含三个整数N,X,Y。
接下来N−1行,每行两个整数描述红树中的一条边。
接下来N−1行,每行两个整数描述蓝树中的一条边。

Output

如果老爷爷能追上鹿,输出双方都在最优策略下时,鹿最多能喝掉最多吨水。否则输出"-1"。

Sample Input

## Sample Input 1
    4 1 2
    1 2
    1 3
    1 4
    2 1
    2 3
    1 4
    
## Sample Input 2
    3 3 1
    1 2
    2 3
    1 2
    2 3
    
## Sample Input 3
    4 1 2
    1 2
    3 4
    2 4
    1 2
    3 4
    1 3
    
## Sample Input 4
    4 2 1
    1 2
    3 4
    2 4
    1 2
    3 4
    1 3
    
## Sample Input 5
    5 1 2
    1 2
    1 3
    1 4
    4 5
    2 1
    1 3
    1 5
    5 4

Sample Output

## Sample Output 1
    4
    
## Sample Output 2
    4
    
## Sample Output 3
    2
    
## Sample Output 4
    -1
    
## Sample Output 5
    6

HINT

2≤N≤2×105
1≤X,Y≤N

存在20分的子任务,满足2≤N≤10。
存在30分的子任务(独立于上一个子任务),满足红树和蓝树结构一样。

分析

orz zzy

先加蓝树边先把蓝树DFS一遍处理出深度

不难想到如果鹿无法到达-1点则会在蓝树中能到达的最深的点处等死

-1点的要求:

与之相连的红树边的端点在蓝树中的距离大于2

加红树边时,把-1边删掉,标记-1点

然后对红树跑一遍BFS,在蓝树中不会被截胡的点才能继续扩张

然后判断一下-1点能否到达

最后找一个能到达的最深的点的,深度*2即为答案

 

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int N=2e5+10;
struct Edge {
    int u,v;
}a[N];
struct Graph {
    int v,nx;
    bool w;
}g[4*N];
int cnt,list[N],dep[N],dis[N],st[N],ed[N],tme,f[N];
bool spec[N],vis[N];
int n,s,t,ans;

void Add(int u,int v,bool w) {
    g[++cnt]=(Graph){v,list[u],w};list[u]=cnt;
    g[++cnt]=(Graph){u,list[v],w};list[v]=cnt;
}

void DFS(int u,int fa) {
    dep[u]=dep[f[u]=fa]+1;st[u]=++tme;
    for (int i=list[u];i;i=g[i].nx)
        if (g[i].v!=fa) DFS(g[i].v,u);
    ed[u]=++tme;
}

int Solve(Edge a) {
    if (st[a.u]>st[a.v]) swap(a.u,a.v);
    if (ed[a.u]>ed[a.v]) if (dep[a.v]-dep[a.u]>2) return spec[a.u]=spec[a.v]=1;
    else return Add(a.u,a.v,1),1;
    if (f[a.u]==f[a.v]) return Add(a.u,a.v,1),1;
    spec[a.u]=spec[a.v]=1;
}

void BFS() {
    queue<int> q;
    q.push(s);vis[s]=1;
    while (!q.empty()) {
        int u=q.front();q.pop();
        for (int i=list[u];i;i=g[i].nx)
            if (g[i].w&&!vis[g[i].v]) {
                dis[g[i].v]=dis[u]+1;
                if (dis[g[i].v]<dep[g[i].v]) q.push(g[i].v),vis[g[i].v]=1;
            }
    }
}

int main() {
    scanf("%d%d%d",&n,&s,&t);
    for (int i=1;i<n;i++) scanf("%d%d",&a[i].u,&a[i].v);
    for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),Add(u,v,0);
    dep[0]=-1;DFS(t,0);
    for (int i=1;i<n;i++) Solve(a[i]);
    BFS();
    for (int i=1;i<=n;i++) if (vis[i]&spec[i]) return printf("-1");
    for (int i=1;i<=n;i++) if (vis[i]) ans=max(ans,dep[i]<<1);
    printf("%d",ans);
}
View Code

 

posted @ 2019-09-18 21:58  Vagari  阅读(283)  评论(0编辑  收藏  举报