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. Ajax全接触(1)

    Ajax全称:Asynchronous JavaScript and XML(异步的JavaScript和XML) .Ajax不是某种编程语言 是一种在无需重新加载整个网页的情况之下能够更新部分网页的 ...

  2. 史上最简单的 SpringCloud 教程 | 第一篇: 服务的注册与发现Eureka(Finchley版本)

    转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springcloud/2018/08/30/sc-f1-eureka/ 本文出自方志朋的博客 一.spring ...

  3. iOS | Swift图片剪切圆角

    我们在IOS开发中,时常需要将一些原本是方形的图片剪切成圆形或者边框是曲线的样子,表现得活泼生动一些. 注意:因为最近在尝试用Swiftl开发,所以这里的语言使用的就是Swift,OC的语法也是相近的 ...

  4. 取消Eclipse的自动代码格式化

    前段时间在Eclipse里面设置了java文件保存时自动格式化,在java->Code Style->Formatter里设置了自定义的格式化的样式,这样每次保存后都会自动格式化代码,用了 ...

  5. 使用Python读取Dbf文件

    DBF:一种特殊的文件格式!表示数据库文件,Foxbase,Dbase,Visual FoxPro等数据库处理系统所产生的数据库文件! DBF 数据库是常用的桌面型数据库,它曾经被各企业.事业单位广泛 ...

  6. 搭建ssm框架经验

    要想搭建好ssm框架的开发环境.首先我们需要知道ssm是什么?ssm就是spring,springmvc,mybatis. 然后我们要知道,他们分别都是怎样实现的和做什么用的,充当什么角色?这样我们就 ...

  7. vue服务端渲染浏览器端缓存(keep-alive)

    在使用服务器端渲染时,除了服务端的接口缓存.页面缓存.组建缓存等,浏览器端也避免不了要使用缓存,减少页面的重绘. 这时候我们就会想到vue的keep-alive,接下来我们说一下keep-alive的 ...

  8. MySQL数据操作(DML)

    表结构准备: mysql> CREATE TABLE student( -> sid INT PRIMARY KEY AUTO_INCREMENT, ), -> age INT, ) ...

  9. laravel 中出现SQLSTATE[HY000] [2002] 如何解决?

    在日常开发中总是难免遇到各式各样的错误,还有许多错误常常是重复出现的 以下是报错信息! SQLSTATE[HY000] [2002] ������ӷ���һ��ʱ���û���ȷ�

  10. js bom和dom

    一, 前言 到目前为止,我们已经学过了JavaScript的一些简单的语法.但是这些简单的语法,并没有和浏览器有任何交互. 也就是我们还不能制作一些我们经常看到的网页的一些交互,我们需要继续学习BOM ...