ps:我的做法是非正规解法,数据水了,就过了。正规解法不会,这里有正规解法的思路:点击打开链接,以后会了再贴。
思路:
分情况讨论,如果操作1多的话,就对2进行搜索,输出答案。如果操作2多的话,就对1进行搜索,用dp[ ]保存,遇到2直接输出。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100005
#define INF 0x3f3f3f3f
using namespace std;
int n,m,ans,cnt,cnt1,cnt2;
bool vis[maxn];
int pp[maxn],c[maxn],dp[maxn];
int x[maxn],y[maxn];
struct Node
{
int v,next;
}edge[2*maxn];
void addedge(int u,int v)
{
cnt++;
edge[cnt].v=v;
edge[cnt].next=pp[u];
pp[u]=cnt;
}
void dfs(int u,int step) //针对操作1多的情况
{
if(step>=ans) return ;
if(c[u])
{
if(ans>step) ans=step;
return ;
}
int i,j,v;
for(i=pp[u];i;i=edge[i].next)
{
v=edge[i].v;
if(!vis[v])
{
vis[v]=1;
dfs(v,step+1);
}
}
}
void dfs1(int u,int step) //针对操作2多的情况
{
if(dp[u]<=step) return ;
dp[u]=step;
int i,j,v;
for(i=pp[u];i;i=edge[i].next)
{
v=edge[i].v;
if(!vis[v])
{
vis[v]=1;
dfs1(v,step+1);
}
}
}
void solve()
{
int i,j;
if(cnt1>cnt2)
{
c[1]=1;
for(i=1;i<=m;i++)
{
if(x[i]==1) c[y[i]]=1;
else
{
ans=INF;
memset(vis,0,sizeof(vis));
vis[y[i]]=1;
dfs(y[i],0);
printf("%d\n",ans);
}
}
}
else
{
memset(dp,0x3f,sizeof(dp));
memset(vis,0,sizeof(vis));
vis[1]=1;
dfs1(1,0);
for(i=1;i<=m;i++)
{
if(x[i]==1)
{
memset(vis,0,sizeof(vis));
vis[y[i]]=1;
dfs1(y[i],0);
}
else printf("%d\n",dp[y[i]]);
}
}
}
int main()
{
int i,j,u,v;
while(~scanf("%d%d",&n,&m))
{
cnt=0;
memset(pp,0,sizeof(pp));
memset(c,0,sizeof(c));
for(i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
cnt1=cnt2=0;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x[i],&y[i]);
if(x[i]==1) cnt1++;
else cnt2++;
}
solve();
}
return 0;
}