【CQOI2017】小Q的棋盘

传送门: NKOJ 4038
这是一道不知道该怎么归类的水题(可能算贪心?),6号大佬说是树形dp(当然可以这样搞)。
我的想法非常简单:
因为出题人保证图连通且“棋子从一个格点移动到另外任一格点的路径是唯一的”,那么这个图应当是树形的,那么,我们就可以乱搞了。

首先求出从0号点出发可以走的最长链长度L(如黄线所示)。
如果行走步数N小于链长(每个点只访问一次,显然最优),结束讨论,可访问的点个数即为N+1。
如果N大于了链长L,那么棋子走到链的终点后无法按照最优的方式继续行走,步数就会被损耗,每两次移动只能访问一个点了(如绿线所示)。因此,可访问的点数就变成了1+L+(N-L)/2了。

以样例2为例:【CQOI2017】小Q的棋盘_第1张图片
以下是代码:
这里写图片描述

#include
#include
const int MAXN=222;
using namespace std;
int V,N,s,t,L,ans;
int To[MAXN],Next[MAXN],Last[MAXN<<1],Pid;
bool vis[MAXN<<1];
void Storepath(int u,int v){
    To[++Pid]=v,Next[Pid]=Last[u],Last[u]=Pid;
}
void GETmxl(int u,int l){
    L=max(L,l),vis[u]=1;
    for(int i=Last[u];i;i=Next[i])
        if(!vis[To[i]])
            GETmxl(To[i],l+1);
}
int main(){
    scanf("%d%d",&V,&N);
    for(int i=1;iscanf("%d%d",&s,&t);
        Storepath(s,t),Storepath(t,s);
    }
    GETmxl(0,0);
    if(Nprintf("%d",N+1);
        return 0;
    }
    ans=min((N+L>>1)+1,V);
    printf("%d",ans);
    return 0;
}

你可能感兴趣的:(水题乱搞)