BFS树

BFS树就是通过bfs遍历一个图构成出来的树,特点就是在无权图上的非树边连接的两点一定在同一层(即深度相同)或者相邻的两层(即深度差的绝对值为1)。
原理:首先bfs树中每个点的深度就是这个点到树根的最短距离,这个想成权值为1的dijkstra就很容易理解,然后如果两个点隔了三层,而他们直接的边的权值为1,那么其中一个深度小的点就可以优化另一个深度大的点,所以这两个点深度绝对值最大为1.
H. Heat Pipes
这个题就是将所有的点的权值赋值为[a,b]中的一个数,使得任意一条边连着的两个点的权值的绝对值为1。
思路:明显染色问题,然后就是找如果奇偶奇偶这样染色,一个联通图的最大权值能染到多大,明显就是bfs树了,最大深度就是最大染色权值,因为bfs树如果根不同,那么最大深度可能不同,所以就n*n暴力bfs求最大深度即可,这个题的细节有点多,比如特判a==b,如果最大颜色超过了b就可以再从b到a循环,然后还要注意不连通。

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int MAX_N=2010;
vector<int>v[MAX_N],area[MAX_N];
int tot=0;
int col[MAX_N],deep[MAX_N];
int flag=1;
void dfs(int x){
 int i;
 if(!flag)
 return ;
 area[tot].push_back(x);
 for(i=0;i<v[x].size();i++){
  int y=v[x][i];
  if(col[y]==col[x]){
   flag=0;
   return ;
  }
  if(col[y])
  continue;
  if(col[x]==1)
  col[y]=2;
  else
  col[y]=1;
  dfs(y);
 }
}
bool vis[MAX_N];
int maxl;
void bfs(int x){
 queue<int>q;
 maxl=0;
 q.push(x);
 deep[x]=1;
 vis[x]=true;
 while(!q.empty()){
  x=q.front();
  q.pop();
  maxl=max(maxl,deep[x]);
  for(int i=0;i<v[x].size();i++){
   int y=v[x][i];
   if(vis[y])
   continue;
   vis[y]=true;
   deep[y]=deep[x]+1;
   q.push(y);
  }
 }
}
int res[MAX_N];
int a,b;
int max_deep[MAX_N];
int k[MAX_N];
int main(void){
 int n,m,i,j,t,x,y;
 int T;
 cin>>T;
 while(T--){
 scanf("%d%d",&n,&m);
 scanf("%d%d",&a,&b);
 for(i=1;i<=n;i++){
  col[i]=0;
  v[i].clear();
  //can[i]=0;
  area[i].clear();
 }
 tot=0;
 flag=1;
 for(i=1;i<=m;i++){
  scanf("%d%d",&x,&y);
  v[x].push_back(y);
  v[y].push_back(x);
 }
 if(a==b){
  if(n==1){
   printf("Yes\n%d\n",a);
  }
  else{
   if(m==0){
    printf("Yes\n");
    for(i=1;i<=n;i++){
     printf("%d",a);
     if(i!=n)
     printf(" ");
     else
     printf("\n");
    }
   }
   else
   printf("No\n");
  }
  continue;
 }
 for(i=1;i<=n;i++){
  if(!flag)
  break;
  if(col[i])
  continue;
  col[i]=1;
  tot++;
  dfs(i);
 }
 if(!flag){
  printf("No\n");
  continue;
 }
 //printf("Yes\n");
 int ff=0;
 int sum=0;
 for(i=1;i<=tot;i++){
  int top=0;
  int maxx;
  for(j=0;j<area[i].size();j++){
   int x=area[i][j];
   for(t=0;t<area[i].size();t++)
   vis[area[i][t]]=0;
   bfs(x);
   if(top<maxl){
    top=maxl;
    maxx=x;
   }
  }
  //cout<<top<<" "<<maxx<<" !!\n";
  for(j=0;j<area[i].size();j++)
  vis[area[i][j]]=0;
  bfs(maxx);
  max_deep[i]=top;
  sum+=top;
 }
 if(sum>=b-a+1)
 ff=1;
 //cout<<sum<<" sum\n";
 if(!ff){
  printf("No\n");
 }
 else{
  printf("Yes\n");
  int st=a;
  int fl=1;
  for(j=1;j<=sum;j++){
   k[j]=st;
   //cout<<j<<" "<<k[j]<<" !!\n";
   if(fl){
    st++;
    if(st>b){
     st=b-1;
     fl=0;
    }
   }
   else{
    st--;
    if(st<a){
     st=a+1;
     fl=1;
    }
   }
  }
  int down=0;
  //cout<<tot<<" tot\n";
  for(i=1;i<=tot;i++){
   for(j=0;j<area[i].size();j++){
    int x=area[i][j];
    res[x]=k[deep[x]+down];
    //cout<<x<<" "<<deep[x]<<"\n";
   }
   down+=max_deep[i];
  }
  for(i=1;i<=n;i++){
   printf("%d",res[i]);
   if(i!=n)
   printf(" ");
   else
   printf("\n");
  }
 }
 }
 return 0;
}//rsb
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值