标签:
还有13天NOI,把各种乱七八糟的算法都重新过一遍还是比较有必要的。。。
//HDU 5046 Airport //DancingLink #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXN 110 #define MAXD MAXN*MAXN #define INF 0x3f3f3f3f #define LL "%lld" typedef long long qword; struct point { qword x,y; }; point pl[MAXN]; qword dis(point p1,point p2) { return abs(p1.x-p2.x)+abs(p1.y-p2.y); } int L[MAXD],R[MAXD],U[MAXD],D[MAXD]; int ptr[MAXN]; int tot[MAXN]; int col[MAXD]; int topd=0; int head=0; void cover(int now) { for (int i=R[now];i!=now;i=R[i]) { for (int j=U[i];j!=i;j=U[j]) { L[R[j]]=L[j]; R[L[j]]=R[j]; } } for (int j=U[now];j!=now;j=U[j]) { L[R[j]]=L[j]; R[L[j]]=R[j]; } } void recover(int now) { for (int i=R[now];i!=now;i=R[i]) for (int j=U[i];j!=i;j=U[j]) L[R[j]]=R[L[j]]=j; for (int j=U[now];j!=now;j=U[j]) L[R[j]]=R[L[j]]=j; } int vv[MAXN]; int ff() { int ret=0; for (int i=R[head];i!=head;i=R[i]) vv[col[i]]=true; for (int i=R[head];i!=head;i=R[i]) { if (vv[col[i]]) { ret++; for (int j=D[i];j!=i;j=D[j]) { for (int k=R[j];k!=j;k=R[k]) { vv[col[k]]=false; } } } } return ret; } bool solve(int trst) { if (L[head]==R[head] && L[head]==head)return true; if (!trst)return false; if (trst<ff())return false; pair<int,int> mnv=make_pair(INF,0); for (int i=R[head];i!=head;i=R[i]) mnv=min(mnv,make_pair(tot[i],i)); int now=mnv.second; for (int i=D[now];i!=now;i=D[i]) { cover(i); if (solve(trst-1))return true; recover(i); } return false; } int main() { freopen("input.txt","r",stdin); int nn; int n,m; int x,y,z; scanf("%d",&nn); int caseid=0; while (nn--) { caseid++; scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf(LL LL ,&pl[i].x,&pl[i].y); memset(ptr,0,sizeof(ptr[0])*(n+10)); memset(tot,0,sizeof(tot[0])*(n+10)); qword l=-1,r=1ll<<33,mid; while (l+1<r) { mid=(l+r)>>1; topd=0; head=++topd; L[head]=R[head]=head; for (int i=1;i<=n;i++) { int np=++topd; col[np]=i; R[np]=head; L[np]=L[head]; L[R[np]]=np; R[L[np]]=np; D[np]=U[np]=np; ptr[i]=np; } for (int i=1;i<=n;i++) { int last=0; for (int j=1;j<=n;j++) { if (dis(pl[i],pl[j])<=mid) { int np=++topd; col[np]=j; tot[ptr[j]]++; D[np]=ptr[j]; U[np]=U[ptr[j]]; D[U[np]]=U[D[np]]=np; if (!last) { L[np]=R[np]=np; }else { L[np]=last; R[np]=R[last]; L[R[np]]=R[L[np]]=np; } last=np; } } } if (solve(m)) { r=mid; }else { l=mid; } } printf("Case #%d: "LL"\n",caseid,r); } }
半年没写DLX了,还能在30分钟内写出来,感觉不错。
DLX分为精确覆盖和完全覆盖,两者的区别大概是在cover和recover之中。
另外DLX也是需要剪枝的。
//bzoj 1135 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXN 210000 #define MAXT MAXN*5 #define lch (now<<1) #define rch (now<<1^1) #define smid ((l+r)>>1) typedef long long qword; struct sgt_node { int lc,rc; qword lx,rx,mx; qword sum; }sgt[MAXT]; void update(int now) { sgt[now].lx=max(sgt[lch].lx,sgt[lch].sum+sgt[rch].lx); sgt[now].rx=max(sgt[rch].rx,sgt[rch].sum+sgt[lch].rx); sgt[now].sum=sgt[lch].sum+sgt[rch].sum; sgt[now].mx=max(max(sgt[lch].mx,sgt[rch].mx),sgt[lch].rx+sgt[rch].lx); } void Build_sgt(int now,int l,int r,int v) { if (l==r) { sgt[now].sum=v; sgt[now].lx=sgt[now].rx=sgt[now].mx=v; return ; } Build_sgt(lch,l,smid,v); Build_sgt(rch,smid+1,r,v); update(now); } void Modify_sgt(int now,int l,int r,int pos,int v) { if (l==r) { sgt[now].sum+=v; sgt[now].lx+=v; sgt[now].rx+=v; sgt[now].mx+=v; return ; } if (pos<=smid) Modify_sgt(lch,l,smid,pos,v); else Modify_sgt(rch,smid+1,r,pos,v); update(now); } int main() { freopen("input.txt","r",stdin); int n,m,t,d; int x,y; scanf("%d%d%d%d",&n,&m,&t,&d); Build_sgt(1,1,n,-t); for (int i=0;i<m;i++) { scanf("%d%d",&x,&y); Modify_sgt(1,1,n,x,y); if (sgt[1].mx>(qword)t*d) { printf("NIE\n"); }else { printf("TAK\n"); } }
hall定理用于二分图匹配相关问题,在要求方案时用贪心或匈牙利算法,运用hall定理有利于优化时间复杂度。
标签:
原文地址:http://www.cnblogs.com/mhy12345/p/4616949.html