标签:ios 引爆 printf 建图 nod logs temp char 三维
所有的坐标都是[0,10^6]的整数
对于30%的数据满足N < 31
对于50%的数据满足N < 101
对于100%的数据满足N < 1001
题解:第一问暴力DP即可,下面考虑第二问。
这题本质上是求最小路径覆盖,所以可以用有上下界的网络流(最小流)解决。这里不说如何建最小流了。不过,由于本题的特殊性质,最小流的第一次dinic一定是满流的,所以我们可以直接进行第二次dinic。第二次的建图方法如下:
1.S -> i 容量1
2.i‘ -> T 容量1
3.i‘ -> i 容量1
4.对于边<i,j> i-> j‘ 容量1
n-最大流即是答案。
#include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <algorithm> using namespace std; int n,ans1,ans2,cnt,S,T; struct node { int x,y,z; }p[1010]; int f[1010],to[2000010],next[2000010],val[2000010],head[2010],d[2010]; queue<int> q; bool cmp(const node &a,const node &b) { return a.x<b.x; } int dfs(int x,int mf) { if(x==T) return mf; int i,k,temp=mf; for(i=head[x];i!=-1;i=next[i]) { if(d[to[i]]==d[x]+1&&val[i]) { k=dfs(to[i],min(temp,val[i])); if(!k) d[to[i]]=0; val[i]-=k,val[i^1]+=k,temp-=k; if(!temp) break; } } return mf-temp; } int bfs() { while(!q.empty()) q.pop(); memset(d,0,sizeof(d)); int i,u; q.push(S),d[S]=1; while(!q.empty()) { u=q.front(),q.pop(); for(i=head[u];i!=-1;i=next[i]) { if(!d[to[i]]&&val[i]) { d[to[i]]=d[u]+1; if(to[i]==T) return 1; q.push(to[i]); } } } return 0; } inline void add(int a,int b,int c) { to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++; to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++; } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘)f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } int main() { n=rd(),S=0,T=2*n+1; int i,j; for(i=1;i<=n;i++) p[i].x=rd(),p[i].y=rd(),p[i].z=rd(); sort(p+1,p+n+1,cmp); memset(head,-1,sizeof(head)); for(i=1;i<=n;i++) { f[i]=1,add(S,i,1),add(i+n,i,1),add(i+n,T,1); for(j=1;j<i;j++) if(p[j].x<p[i].x&&p[j].y<p[i].y&&p[j].z<p[i].z) f[i]=max(f[i],f[j]+1),add(j,i+n,1); ans1=max(ans1,f[i]); } printf("%d\n",ans1); while(bfs()) ans2+=dfs(S,1<<30); printf("%d",n-ans2); return 0; }
【BZOJ2044】三维导弹拦截 DP+(有上下界的)网络流
标签:ios 引爆 printf 建图 nod logs temp char 三维
原文地址:http://www.cnblogs.com/CQzhangyu/p/7586468.html