题目链接

给出一棵树, 树上点的值为0或1, 可以交换树上两个点的权值, 给出一个距离m, 所有的0距离最近的1的距离不能超过m, 求最少的交换次数。

首先对于每一个点u,所有离u的距离不超过m的点v, 加一条边(u, v)。

然后dlx, 剪枝的函数是当前1的个数+还需要的1的个数不超过1的总数, 具体看代码。

 #include<bits/stdc++.h>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, a, n) for(int i = a; i<n; i++)
#define ull unsigned long long
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-;
const int mod = 1e9+;
const int inf = ;
const int dir[][] = { {-, }, {, }, {, -}, {, } };
const int maxn = ;
const int maxNode = ;
int head[maxn], num;
struct node
{
int to, nextt, c;
}e[maxn];
void addEdge(int u, int v, int c) {
e[num].to = v;
e[num].nextt = head[u];
e[num].c = c;
head[u] = num++;
}
struct DLX {
int L[maxNode], R[maxNode], U[maxNode], D[maxNode], row[maxNode], col[maxNode];
int S[maxn], H[maxn], deep, ans[maxn], sz, n, m, kind[maxn], boy_num;
void remove(int c) {
for(int i = D[c]; i!=c; i = D[i]) {
L[R[i]] = L[i];
R[L[i]] = R[i];
}
}
void resume(int c) {
for(int i = U[c]; i!=c; i = U[i]) {
L[R[i]] = i;
R[L[i]] = i;
}
}
int h() {
int cnt = ;
int vis[];
mem(vis);
for(int i = R[]; i!=; i = R[i]) {
if(!vis[i]) {
cnt++;
vis[i] = ;
for(int j = D[i]; j!=i; j = D[j]) {
for(int k = R[j]; k!=j; k = R[k]) {
vis[col[k]] = ;
}
}
}
}
return cnt;
}
void dfs(int d, int cnt) {
if(d+h()>boy_num||cnt>=deep)
return ;
if(R[] == ) {
deep = min(deep, cnt);
return ;
}
int c = R[];
for(int i = R[]; i!=; i = R[i])
if(S[c]>S[i])
c = i;
for(int i = D[c]; i!=c; i = D[i]) {
remove(i);
for(int j = R[i]; j!=i; j = R[j])
remove(j);
dfs(d+, cnt+(!kind[row[i]]));
for(int j = L[i]; j!=i; j = L[j])
resume(j);
resume(i);
}
return ;
}
void add(int r, int c) {
sz++;
row[sz] = r;
col[sz] = c;
S[c]++;
U[sz] = U[c];
D[sz] = c;
D[U[c]] = sz;
U[c] = sz;
if(~H[r]) {
R[sz] = H[r];
L[sz] = L[H[r]];
L[R[sz]] = sz;
R[L[sz]] = sz;
} else {
H[r] = L[sz] = R[sz] = sz;
}
}
void init(){
mem1(H);
num = boy_num = ;
mem1(head);
deep = inf;
for(int i = ; i<=n; i++) {
R[i] = i+;
L[i] = i-;
U[i] = i;
D[i] = i;
}
mem(S);
R[n] = ;
L[] = n;
sz = n;
}
void dfs(int u, int root, int fa, int d) {
add(root, u);
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to, c = e[i].c;
if(v == fa)
continue;
if(c+d<=m)
dfs(v, root, u, d+c);
}
}
void solve() {
init();
int u, v, c;
for(int i = ; i<=n; i++) {
scanf("%d", &kind[i]);
boy_num+=kind[i];
}
for(int i = ; i<n-; i++) {
scanf("%d%d%d", &u, &v, &c);
addEdge(u, v, c);
addEdge(v, u, c);
}
for(int i = ; i<=n; i++) {
dfs(i, i, -, );
}
dfs(, );
if(deep == inf)
deep = -;
cout<<deep<<endl;
}
}dlx;
int main()
{
int t;
cin>>t;
for(int i = ; i<=t; i++) {
printf("Case #%d: ", i);
scanf("%d%d", &dlx.n, &dlx.m);
dlx.solve();
}
return ;
}

最新文章

  1. java 排序
  2. Hadoop集群搭建安装过程(三)(图文详解---尽情点击!!!)
  3. UTF-8-BOM
  4. Linux学习之路一计算机是如何工作的
  5. QT 小票打印
  6. uboot1.1.6之NOR FLASH 出现的问题解决方法
  7. Java线程:线程交互
  8. 指针变量的*p,p以及&amp;p的区别
  9. IntelliJ IDEA开发Scala代码,与java集成,maven打包编译
  10. SAS 统计某个数据集各个字段频数,并汇集到一个表中
  11. linux安装jdk8
  12. Evaluate Reverse Polish Notation (STRING-TYPE CONVERTION)
  13. C# 等值锁定
  14. 回归(regression)、梯度下降(gradient descent)
  15. getQueryString----获取url中得参数
  16. Eclipse中Next Difference的快捷键
  17. ajax多次请求的一个效果思路
  18. CSDN开源夏令营 基于Compiz的switcher插件设计与实现之前期准备 git的简单使用
  19. Leetcode 20 有效的括号valid-parentheses(栈)
  20. 深入Vue.js从源码开始(二)

热门文章

  1. arcgis切图问题
  2. 轻量级的数据交换语言(JSON)
  3. Sublime Text3 插件安装教程
  4. OpenCV学习(1) RGB颜色空间
  5. 加密传输SSL协议1_OpenSSL的安装
  6. 将数据从服务器端同步到手机上, 并且需要离线工作,Couchebase Mobile 也许是目前最好的解决方案:
  7. php的模板引擎
  8. hdu 2276 Kiki &amp; Little Kiki 2 矩阵快速幂
  9. java面向对象之 封装 Encapsulation
  10. jQuery Pagination Plugin ajax分页控件