HDU 4735 Little Wish~ lyrical step~(DLX , 重复覆盖)

解题思路:

DLX 的模板题,重复覆盖。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#define FOR(i,x,y) for(int i=x;i<=y;i++)
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 7500;
int boys , boy[100];
struct DLX
{
    #define FF(i,A,s) for(int i = A[s];i != s;i = A[i])
    int L[maxn],R[maxn],U[maxn],D[maxn];
    int size,col[maxn],row[maxn],s[maxn],H[100];
    bool vis[100];
	int ans[maxn],cnt;
    void init(int m)
    {
        for(int i=0;i<=m;i++)
		{
            L[i] = i - 1;R[i] = i + 1;U[i] = D[i] = i;s[i] = 0;
        }
        memset(H,-1,sizeof(H));
        L[0] = m;R[m] = 0;size = m + 1;
    }
	void link(int r,int c)
	{
         U[size] = c;D[size] = D[c];U[D[c]] = size;D[c] = size;
         if(H[r]<0)H[r] = L[size] = R[size] = size;
         else
		 {
             L[size] = H[r];R[size] = R[H[r]];
             L[R[H[r]]] = size;R[H[r]] = size;
         }
         s[c]++;col[size] = c;row[size] = r;size++;
     }
	void del(int c)
	{
        L[R[c]] = L[c] ; R[L[c]] = R[c];
        FF(i,D,c)FF(j,R,i)U[D[j]] = U[j],D[U[j]] = D[j],--s[col[j]];
    }
    void add(int c)
    {
        R[L[c]] = L[R[c]] = c;
        FF(i,U,c)FF(j,L,i)++s[col[U[D[j]] = D[U[j]] = j]];
    }
	bool dfs(int k)
	{
        if(!R[0])
		{
            cnt = k;return 1;
        }
        int c = R[0];FF(i,R,0)if(s[c] > s[i])c = i;
        del(c);
        FF(i, D, c)
        {
            FF(j, R, i) del(col[j]);
            ans[k] = row[i];if(dfs(k + 1))return true;
            FF(j,L,i) add(col[j]);
        }
        add(c);
        return 0;
    }
    void remove(int c)
    {
        FF(i, D, c)L[R[i]] = L[i],R[L[i]] = R[i];
    }
     void resume(int c)
     {
         FF(i, U, c)L[R[i]] = R[L[i]] = i;
     }
    int A()
    {
        int res = 0;
        memset(vis,0,sizeof(vis));
        FF(i, R, 0)if(!vis[i])
        {
			res++;vis[i] = 1;
			FF(j, D, i)FF(k, R, j)vis[col[k]] = 1;
		}
        return res;
    }
    void Dance(int now, int &lim)
    {
		if(now + A() > boys) return ; int tt = 0;
		for(int i=0;i<now;i++)tt += boy[ans[i]];
		if(now - tt >= lim) return;
		if(!R[0])
		{
			lim = now - tt;
			return;
		}
        int temp = INF , c;
        FF(i,R,0)if(temp >= s[i])temp = s[i] , c = i;
        FF(i, D, c)
        {
			ans[now] = row[i];
            remove(i);FF(j, R, i)remove(j);
            Dance(now + 1, lim);
            FF(j, L, i)resume(j);resume(i);
        }
    }
}dlx;
int N , D;
int d[100][100];
int main()
{
	int T , kcase = 1;
	scanf("%d", &T);
	while(T--)
	{
		scanf("%d%d", &N, &D);dlx.init(N);
		boys = 0; FOR(i, 1, N) scanf("%d", &boy[i]) , boys += boy[i];
		FOR(i, 1, N) FOR(j, 1, N) d[i][j] = (i == j ? 0 : INF);
		FOR(i, 1, N-1)
		{
			int u , v , w;
			scanf("%d%d%d",&u,&v,&w);
			d[u][v] = d[v][u] = w;
		}

		FOR(k, 1, N)
		FOR(i, 1, N)
		FOR(j, 1, N)
			if(d[i][j] > d[i][k] + d[k][j])
				d[i][j] = d[i][k] + d[k][j];

		FOR(i, 1, N) FOR(j, 1, N)
		if(d[i][j] <= D) dlx.link(i, j);
		int ans = INF;
		dlx.Dance(0, ans);
		if(ans > boys) ans = -1;
		printf("Case #%d: %d\n", kcase++, ans);
	}
	return 0;
}
时间: 2024-08-06 01:10:59

HDU 4735 Little Wish~ lyrical step~(DLX , 重复覆盖)的相关文章

hdu 4735 Little Wish~ lyrical step~(DLX)

题目链接:hdu 4735 Little Wish~ lyrical step~ 题意: 有n个节点的树,每个节点可能是男孩,可能是女孩,节点之间有距离,现在要让所有的女孩周围距离D之内有男孩,问最小需要交换多少次男孩和女孩的位置. 题解: 把每个节点对小于D距离的全部link起来,然后DLX爆艹,意义就是选n个节点去覆盖全部节点,如果这个节点是女生,那么就是要替换的点.然后不断更新答案. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int

[DLX重复覆盖] hdu 4735 Little Wish~ lyrical step~

题意: 在一棵树上有n个节点,n-1条边,每条边有距离. 每个节点会给你原来是男孩还是女孩. 问最少要交换多少次,使得每个女孩都能被保护到. 保护到的条件是女孩和最近的男孩的距离小于等于D 思路: 首先要求一下mp[i][j],就是任意两个点之间的距离 这个方法随意都可以的. 因为男孩只能放在树上,所以行为树,列也为树 这样每次求出的cnt就是每次最多要有多少个男的在指定的树上 这时候就需要剪枝了 剪枝就是 1.如果x+h()>boy 需要男生数超过总的男生数 return 2.每次遍历一遍当前

(中等) HDU 4979 A simple math problem. , DLX+重复覆盖+打表。

Description Dragon loves lottery, he will try his luck every week. One day, the lottery company brings out a new form of lottery called accumulated lottery. In a normal lottery, you pick 7 numbers from N numbers. You will get reward according to how

HDU 5046 Airport(DLX重复覆盖)

HDU 5046 Airport 题目链接 题意:给定一些机场,要求选出K个机场,使得其他机场到其他机场的最大值最小 思路:二分+DLX重复覆盖去判断即可 代码: #include <cstdio> #include <cstring> using namespace std; const int MAXNODE = 4005; const int MAXM = 65; const int MAXN = 65; const int INF = 0x3f3f3f3f; int K;

[ACM] HDU 2295 Radar (二分+DLX 重复覆盖)

Radar Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2593    Accepted Submission(s): 1012 Problem Description N cities of the Java Kingdom need to be covered by radars for being in a state of

[DLX重复覆盖] hdu 2828 Lamp

题意: 有N个灯M个开关 每个灯的ON和OFF状态都能控制一个灯是否亮 给出N行,代表对于每个灯 哪些开关的哪个状态可以使得第i个灯亮 思路: 这里需要注意一个问题 如果开关1的ON 状态和开关2的ON状态能使得1号灯亮 那么开关1.2同时处于ON的时候 1号灯也是亮的.意思就是只要有一个开关使得灯亮,灯就亮了. 简单的DLX 重复覆盖 行为每个开关的两个状态2*m行,列为n个灯 在搜索的同时标记一下哪个开关被用过了 那么另一个状态也不能用了 代码: #include"stdio.h"

HDU 2295 Radar( 二分+Dancing Links重复覆盖 )

题意 : 有 n 个城市 , m个站 , 你要选择 k 个站 , 每个站画一个半径为 r 的圆 , 可以覆盖所有的城市 , 一个城市可以被多个站覆盖 .求的是满足要求的最小的 r . 思路很明显了 , 首先是二分 , 将问题转化成可行性判定的问题 . 那么对于 mid , 我们将 站看成行 , 将城市看成 列 , 如果一个站和一个城市的距离小于mid , 那么对应的矩阵位置的值就1 , 否则是0 , 用dlx 重复覆盖来解决 重复覆盖和精确覆盖主要有两个区别 : 第一, remove 和 res

FZU 1686 神龙的难题(DLX重复覆盖)

FZU 1686 神龙的难题 题目链接 题意:中文题 思路:每一个1看成列,每个位置作为左上角的矩阵看成行,dlx重复覆盖即可 代码: #include <cstdio> #include <cstring> using namespace std; const int MAXNODE = 66666; const int INF = 0x3f3f3f3f; const int MAXM = 230; const int MAXN = 230; int K; struct DLX

FZU 1686 神龙的难题 DLX重复覆盖

DLX重复覆盖: 需要一个A*函数剪支 Problem 1686 神龙的难题 Accept: 462    Submit: 1401 Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description 这是个剑与魔法的世界.英雄和魔物同在,动荡和安定并存.但总的来说,库尔特王国是个安宁的国家,人民安居乐业,魔物也比较少.但是.总有一些魔物不时会进入城市附近,干扰人民的生活.就要有一些人出来守护居民们不被魔物侵害.魔法使艾米莉