给一棵树,每个节点上有一个男孩或女孩,要求每个女孩节点,距离她距离d的范围内至少有一个男孩节点。可以选择两个节点交换他们的位置,问最少需要交换多少次可以满足要求。直接DLX爆搜一遍就好了。。好久没写DLX都忘得差不多了居然调了大半天,也算是大攒人品了,同时也正好赶在省赛,网赛前复习一下DLX...
/*=============================================================================
# Author:Erich
# FileName:
=============================================================================*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#define lson id<<1,l,m
#define rson id<<1|1,m+1,r
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=1ll<<60;
const double PI=acos(-1.0);
const int maxn=3055;
int g[55][55];
int res;
int boys;
int n,m,d;
bool mark[55];
struct DLX
{
int col[maxn],row[maxn],ans[55];
int S[55],H[55];
int size,cnt;
int U[maxn],R[maxn],D[maxn],L[maxn];
int h()
{
bool hs[55];
memset(hs,0,sizeof hs);
int ret=0;
for (int i=R[0]; i!=0; i=R[i])
{
if (!hs[i])
{
ret++;
hs[i]=true;
for (int j1=D[i]; j1!=i; j1=D[j1])
for (int j2=R[j1]; j2!=j1; j2=R[j2])
hs[col[j2]]=true;
}
}
return ret;
}
/*int hh(int x)
{
int res=0;
for (int i=0; i<x; i++)
if (!mark[ans[i]]) res++;
return res;
}*/
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;
}
}
void dance(int p)
{
if (p+h()>boys) return ;
if (p>boys) return ;
int tt=0;
for (int i=0; i<p; i++)
if (!mark[ans[i]]) tt++;
if (tt>=res) return ;
int c=R[0];
if (c==0)
{
// for (int i=0; i<p; i++) cout<<ans[i]<<" ";
// cout<<endl;
res=min(tt,res);
return ;
}
for (int i=R[0]; i!=0; i=R[i])
if (S[i]<S[c]) c=i;
for (int i=D[c]; i!=c; i=D[i])
{
ans[p]=row[i];
remove(i);
for (int j=R[i]; j!=i; j=R[j]) remove(j);
dance(p+1);
for (int j=L[i]; j!=i; j=L[j]) resume(j);
resume(i);
}
}
void init(int n)
{
for (int i=0; i<=n; i++)
{
S[i]=0;
L[i]=i-1;
R[i]=i+1;
U[i]=D[i]=i;
}
L[0]=n;
R[n]=0;
size=n+1;
memset(H,-1,sizeof H);
}
void link(int x,int y)
{
++S[col[size]=y];
row[size]=x;
D[size]=D[y];
U[D[y]]=size;
U[size]=y;
D[y]=size;
if (H[x]<0) H[x]=L[size]=R[size]=size;
else
{
R[size]=R[H[x]];
L[R[H[x]]]=size;
L[size]=H[x];
R[H[x]]=size;
}
size++;
}
void print()
{
int c=R[0];
for (c=R[0]; c!=0; c=R[c])
{
for (int i=D[c]; i!=c; i=D[i])
cout<<col[i]<<" "<<row[i]<<endl;
}
}
}dlx;
int main()
{
// freopen("in.txt","r",stdin);
int tt;
scanf("%d",&tt);
int cnt=0;
while(tt--)
{
printf("Case #%d: ",++cnt);
scanf("%d%d",&n,&d);
int x,y,z;
boys=0;
for (int i=1; i<=n; i++)
{
scanf("%d",&x);
mark[i]=(x==1);
if (mark[i]) boys++;
}
memset(g,0x3f,sizeof g);
for (int i=1; i<=n; i++) g[i][i]=0;
for (int i=1; i<n; i++)
{
scanf("%d%d%d",&x,&y,&z);
g[x][y]=g[y][x]=z;
}
for (int k=1; k<=n; k++)
for (int i=1; i<=n; i++)
if (i!=k)
for (int j=1; j<=n; j++)
if (i!=j && j!=k)
{
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
dlx.init(n);
res=inf;
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
if (g[i][j]<=d) dlx.link(i,j);
//dlx.print();
dlx.dance(0);
if (res==inf) puts("-1");
else printf("%d\n",res);
}
return 0;
}