HDU 3974 Assign the task 并查集+非路径压缩

题目链接:题目传送门
题目大意:
现有一棵树,有以下操作:

  1. 节点x及其所有子孙颜色都变更为k。
  2. 要求你回答节点x的颜色。
    初始所有点都没有染色。
    Input
    第一行一个整数T(T <= 10),表示样例组数。
    对于每个测试样例:
    第一行一个整数n(n <= 5e4),表示树的节点个数。
    接下来n行,每行两个整数u, v(1 <= u, v <= n),表示树中u的父节点是v。
    接下来一行一个整数q(q <= 5e4),表示询问数。
    接下来q行:
    若为染色操作则输入“T x k”,若为查询操作则输入“C x”,(1 <= x <= n, 0 <= y <= 1e9)。
    Output
    每个测试样例首先输出一行"Case #x:",其中x为当前样例编号。
    对于每个询问操作输出一个整数,表示当前节点的颜色,若还未染色则输出-1。
    Sample Input
1 
5 
4 3 
3 2 
1 3 
5 2 
5 
C 3 
T 2 1
 C 3 
T 3 2 
C 3

Sample Output

Case #1:
-1 
1 
2

思路:
一看是树形结构,不是dfs序就是并查集,dfs需要和线段树以及时间戳结合,因此并查集简单些,但是这里不能用路劲压缩(我就错在这里),**因为路径压缩找的时根节点不是父子节点,**看代码。
代码:

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long int ll;
const ll N = 5e4 + 100;
ll color[N],f[N],time[N];
int main()
{
 ios::sync_with_stdio(false);
 int t,n;
 cin>>t;
 int flag=0;
 while(t--)
 {
  flag++;
  cin>>n;
  for(int i=1;i<=n;i++)
  {
   f[i]=i;
   color[i]=-1;
   time[i]=-1;
  }
  for(int i=1;i<n;i++)
  {
   int x,y;
   cin>>x>>y;
   f[x]=y;//记录父子关系 
  }
  int q,cnt=0;
  cin>>q;
  cout<<"Case #"<<flag<<":"<<'\n';
  while(q--)
  {
   char p;
   int x,y;
   cin>>p;
   if(p=='C')
   {
    cin>>x;
    int cnr=x,ans=color[cnr],lastt=-1;
    while(cnr!=f[cnr])
    {
     if(time[cnr]>lastt)//证明在这个点被改变颜色了,改变的更晚些 
     {
      lastt=time[cnr]; 
      ans=color[cnr];
     }
     cnr=f[cnr];//父子节点,向上寻找 
    }
    if(time[cnr]>lastt)
    {
     lastt=time[cnr];
     ans=color[cnr];
    }//再判断下 ,因为最上面的根节点也可能改变颜色了 
    cout<<ans<<'\n';
    
   }
   else if(p=='T')
   {
    cin>>x>>y;
    color[x]=y;
    time[x]=cnt++;
   }
  }
 }
 return 0; 
}

你可能感兴趣的:(数据结构)