hdu4735 Little Wish~ lyrical step~ DLX重複覆蓋

     給一棵樹,每個節點上有一個男孩或女孩,要求每個女孩節點,距離她距離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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章