Description

N children are living in a tree with exactly N nodes, on each node there lies either a boy or a girl.  A girl is said to be protected, if the distance between the girl and her nearest boy is no more than D.  You want to do something good, so that each girl on the tree will be protected. On each step, you can choose two nodes, and swap the children living on them. What is the minimum number of steps you have to take to fulfill your wish?
 

Input

The first line has a number T (T <= 150) , indicating the number of test cases.  In a case, the first line contain two number n (1 <= n <= 50), D (1 <= D <= 10000000), Which means the number of the node and the distance between the girls and boys.  The next lines contains n number. The i th number means the i th node contains a girl or a boy. (0 means girl 1 means boy), The follow n - 1 lines contains a, b, w, means a edge connect a th node and b th node, and the length of the edge is w (1 <= w <= 10000000).
 

Output

For every case, you should output "Case #t: " at first, without quotes. The t is the case number starting from 1.  Then follows the answer, -1 meas you can't comlete it, and others means the minimum number of the times.

题目大意:一棵树上有n个结点,每个结点有一个男生或者一个妹纸,每条边有一个距离,问最少交换多少个人,使得妹纸在距离D内至少有一个男生。。。

思路:换句话说,这题可以理解为:交换多少个0或1,使得每个结点在D的距离内有一个1(1的男孩纸)。

那么用DLX搜索,每一列代表一个点。每一行代表一个点,每行的结点为这个点为1可以保护的所有点(包括自己)。

然后套DLX。

加入两个剪枝:搜索到的交换若大于当前答案,则剪枝。在每一层作一个乐观估计,估计最少还需要选出多少个点,若大于点为1的点数,则剪枝。

这题正解大概为DP。我不会。

代码(1171MS):

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std; const int MAXN = ;
const int MAXC = MAXN;
const int MAXR = MAXN;
const int MAXP = MAXR * MAXN + MAXC; int boy[MAXN];
int mat[MAXN][MAXN];
int n, D, boys; struct DLX {
int n, sz;//列数,结点总数
int sum[MAXC];//每列拥有的结点数
int row[MAXP], col[MAXP];//结点所在的行和列
int left[MAXP], right[MAXP], up[MAXP], down[MAXP];//十字链表
int ans, anst[MAXR]; void init(int nn) {
n = nn;
for(int i = ; i <= n; ++i) {
up[i] = down[i] = i;
left[i] = i - ; right[i] = i + ;
col[i] = i;
}
right[n] = ; left[] = n;
sz = n + ;
memset(sum, , sizeof(sum));
} void add_row(int r, vector<int> &columns) {
int first = sz;
for(int i = , len = columns.size(); i < len; ++i) {
int c = columns[i];
left[sz] = sz - ; right[sz] = sz + ; down[sz] = c; up[sz] = up[c];
down[up[c]] = sz; up[c] = sz;
row[sz] = r; col[sz] = c;
++sum[c]; ++sz;
}
right[sz - ] = first; left[first] = sz - ;
} void remove(int c) {
for(int i = down[c]; i != c; i = down[i]) {
left[right[i]] = left[i];
right[left[i]] = right[i];
}
} void restore(int c) {
for(int i = down[c]; i != c; i = down[i]) {
left[right[i]] = i;
right[left[i]] = i;
}
} bool vis[MAXC]; int A() {
memset(vis, , sizeof(vis));
int ret = ;
for(int i = right[]; i != ; i = right[i]) if(!vis[i]) {
++ret;
for(int j = down[i]; j != i; j = down[j]) {
for(int k = right[j]; k != j; k = right[k]) vis[col[k]] = true;
}
}
return ret;
} void dfs(int dep) {
if(dep + A() > boys) return ;
int tmp = ;
for(int i = ; i < dep; ++i) tmp += boy[anst[i]];
if(dep - tmp >= ans) return ;
if(right[] == ) {
ans = dep - tmp;
return ;
}
int c = right[];
for(int i = right[]; i != ; i = right[i]) if(sum[i] < sum[c]) c = i;
for(int i = down[c]; i != c; i = down[i]) {
anst[dep] = row[i];
remove(i);
for(int j = right[i]; j != i; j = right[j]) remove(j);
dfs(dep + );
for(int j = left[i]; j != i; j = left[j]) restore(j);
restore(i);
}
} bool solve() {
ans = n + ;
dfs();
return ans != n + ;
}
} S; void floyd() {
for(int k = ; k <= n; ++k)
for(int i = ; i <= n; ++i) if(mat[i][k] <= D)
for(int j = ; j <= n; ++j) if(mat[k][j] <= D)
mat[i][j] = min(mat[i][j], mat[i][k] + mat[k][j]);
} int main() {
int T; scanf("%d", &T);
for(int t = ; t <= T; ++t) {
scanf("%d%d", &n, &D);
memset(mat, 0x3f, sizeof(mat));
boys = ;
for(int i = ; i <= n; ++i) scanf("%d", &boy[i]), boys += boy[i];
for(int i = ; i < n; ++i) {
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
mat[u][v] = mat[v][u] = c;
}
for(int i = ; i <= n; ++i) mat[i][i] = ;
floyd();
S.init(n);
for(int i = ; i <= n; ++i) {
vector<int> columns;
for(int j = ; j <= n; ++j) if(mat[i][j] <= D) columns.push_back(j);
S.add_row(i, columns);
}
bool flag = S.solve();
printf("Case #%d: ", t);
if(flag) printf("%d\n", S.ans);
else puts("-1");
}
}

HDU 4735 Little Wish~ lyrical step~(DLX搜索)(2013 ACM/ICPC Asia Regional Chengdu Online)的更多相关文章

  1. HDU 4729 An Easy Problem for Elfness(主席树)(2013 ACM/ICPC Asia Regional Chengdu Online)

    Problem Description Pfctgeorge is totally a tall rich and handsome guy. He plans to build a huge wat ...

  2. HDU 4747 Mex(线段树)(2013 ACM/ICPC Asia Regional Hangzhou Online)

    Problem Description Mex is a function on a set of integers, which is universally used for impartial ...

  3. HDU 4291 A Short problem(2012 ACM/ICPC Asia Regional Chengdu Online)

    HDU 4291 A Short problem(2012 ACM/ICPC Asia Regional Chengdu Online) 题目链接http://acm.hdu.edu.cn/showp ...

  4. HDU 5874 Friends and Enemies 【构造】 (2016 ACM/ICPC Asia Regional Dalian Online)

    Friends and Enemies Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  5. HDU 4063 Aircraft(计算几何)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4063 Description You are playing a flying game. In th ...

  6. HDU 4031 Attack(离线+线段树)(The 36th ACM/ICPC Asia Regional Chengdu Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4031 Problem Description Today is the 10th Annual of ...

  7. HDU 4749 Parade Show 2013 ACM/ICPC Asia Regional Nanjing Online

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4749 题目大意:给一个原序列N,再给出一个序列M,问从N中一共可以找出多少个长度为m的序列,序列中的数 ...

  8. [2013 ACM/ICPC Asia Regional Nanjing Online C][hdu 4750]Count The Pairs(kruskal + 二分)

    http://acm.hdu.edu.cn/showproblem.php?pid=4750 题意: 定义f(u,v)为u到v每条路径上的最大边的最小值..现在有一些询问..问f(u,v)>=t ...

  9. HDU 4751 Divide Groups 2013 ACM/ICPC Asia Regional Nanjing Online

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4751 题目大意:判断一堆人能否分成两组,组内人都互相认识. 解题思路:如果两个人不是相互认识,该两人之 ...

随机推荐

  1. 面向对象编程——class继承

    在上面的章节中我们看到了JavaScript的对象模型是基于原型实现的.特点是简单,缺点是理解起来比传统类-实例模型要困难,最大的缺点是继承的实现需要编写大量代码,并且需要正确实现原型链. 新的关键字 ...

  2. 与JSON相关的问题

    1.JSON.stringify 与 JSON.parse 相关的问题 JSON.stringify 把字符串转化为字符串,JSON.parse把字符串转化为JSON格式 会出现的问题Unexpect ...

  3. Vue组件通讯黑科技

    Vue组件通讯 组件可谓是 Vue框架的最有特色之一, 可以将一大块拆分为小零件最后组装起来.这样的好处易于维护.扩展和复用等. 提到 Vue的组件, 相必大家对Vue组件之间的数据流并不陌生.最常规 ...

  4. HTML中footer固定在页面底部的若干种方法

    <div class="header"><div class="main"></div></div> <d ...

  5. (暴力碾标算)NOIP模拟赛 宗教仪式

    题意: 一个模式串,一个文本串,现定义最大失配值为k 求文本中最大失配值<=k的长度为len(模式串)的字串个数 失配值=当前字串中与模式串不同的字符个数 思路: 暴力,加一个跳出剪枝,居然过了 ...

  6. harbor中碰到的问题

    harbor部署整体比较简单,但是就是这么简单的东西稍微改变点配置文件就会有不小的问题 1.问题1 部署harbor1.6发现web界面删除的镜像在push一遍上去后,镜像大小为0 且无法删除,这个问 ...

  7. php判断某个数是素数的3种方法

    什么是素数? 质数又称素数.一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数:否则称为合数.(注:1不是素数.) 方法一: 基本方法,——计数方法. $num = 7; $n = ...

  8. 【tp5.1】微信公众号授权登录及获取信息录入数据库

    微信公众号开发文档链接:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432 微信公众号授权登录分为两种: 1.以 ...

  9. 自定义控件,继承自 ListView

    public class MyListView extends ListView { /** * 如果在xml中创建并设置了style,就会调用三个参数的. * * @param context * ...

  10. Windows使用Node.js自动生成Vue.js模版环境部署步骤-----记录

    node.js官网下载并安装node 进入node文档目录下,运行cmd 输入 node -v 查看node版本 出现表示安装完成 输入 npm -v 显示npm版本信息 安装cnpm 输入 npm ...