Description
一场战争正在A国与B国之间如火如荼的展开。 B国凭借其强大的经济实力开发出了无数的远程攻击导弹,B国的领导人希望,通过这些导弹直接毁灭A国的指挥部,从而取得战斗的胜利!当然,A国人民不会允许这样的事情发生,所以这个世界上还存在拦截导弹。 现在,你是一名A国负责导弹拦截的高级助理。 B国的导弹有效的形成了三维立体打击,我们可以将这些导弹的位置抽象三维中间的点(大小忽略),为了简单起见,我们只考虑一个瞬时的状态,即他们静止的状态。 拦截导弹设计非常精良,可以精准的引爆对方导弹而不需要自身损失,但是A国面临的一个技术难题是,这些导弹只懂得直线上升。精确的说,这里的直线上升指xyz三维坐标单调上升。 给所有的B国导弹按照1至N标号,一枚拦截导弹可以打击的对象可以用一个xyz严格单调上升的序列来表示,例如: B国导弹位置:(0, 0, 0) (1, 1, 0) (1, 1, 1), (2, 2, 2) 一个合法的打击序列为:{1, 3, 4} 一个不合法的打击序列为{1, 2, 4} A国领导人将一份导弹位置的清单交给你,并且向你提出了两个最简单不过的问题(假装它最简单吧): 1.一枚拦截导弹最多可以摧毁多少B国的导弹? 2.最少使用多少拦截导弹才能摧毁B国的所有导弹? 不管是为了个人荣誉还是国家容易,更多的是为了饭碗,你,都应该好好的把这个问题解决掉!
Input
第一行一个整数N给出B国导弹的数目。 接下来N行每行三个非负整数Xi, Yi, Zi给出一个导弹的位置,你可以假定任意两个导弹不会出现在同一位置。
Output
第一行输出一个整数P,表示一枚拦截导弹之多能够摧毁的导弹数。 第二行输出一个整数Q,表示至少需要的拦截导弹数目。
Sample Input
4
0 0 0
1 1 0
1 1 1
2 2 2
Sample Output
3
2
解题思路
拓扑排序+最小路径覆盖
代码:
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<queue>
using namespace std;
struct ldx
{
int x,y,z;
}s[1005];
queue <int> q;
int hed[1005],nex[1000005],lb[1000005],ru[1000005];
int pa[1005];
int n,ans=0,lo=0;
void add(int x,int y)
{
lo++;
nex[lo]=hed[x];
hed[x]=lo;
lb[lo]=y;
}
int had[2005],nax[2000005],lab[2000005],cap[2000005],dep[2005];
int loo=-1,si=2002,t=2003,mx=2147483640;
void add1(int x,int y,int num)
{
loo++;
nax[loo]=had[x];
had[x]=loo;
lab[loo]=y;
cap[loo]=num;
}
int dfs(int x,int num)
{
if(x==t || num==0) return num;
int c=0;
for(int i=had[x];i!=-1;i=nax[i])
if(dep[lab[i]]==dep[x]+1 && cap[i])
{
int f=dfs(lab[i],min(num,cap[i]));
c+=f;
num-=f;
cap[i]-=f;
cap[i^1]+=f;
if(num==0) break;
}
if(c==0) dep[x]=-1;
return c;
}
bool bfs()
{
memset(dep,0,sizeof(dep));
queue <int> qi;
qi.push(si);
dep[si]=1;
while(!qi.empty())
{
int x=qi.front();
qi.pop();
for(int i=had[x];i!=-1;i=nax[i])
if(!dep[lab[i]] && cap[i])
{
dep[lab[i]]=dep[x]+1;
qi.push(lab[i]);
}
}
return dep[t];
}
int dinic_()
{
int c=0;
while(bfs()) c+=dfs(si,mx);
return c;
}
int main()
{
memset(had,-1,sizeof(had));
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].z);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(s[j].x>s[i].x && s[j].y>s[i].y && s[j].z>s[i].z)
{add(i,j);ru[j]++;}
for(int i=1;i<=n;i++)
if(ru[i]==0) {pa[i]=1;q.push(i);}
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=hed[x];i!=0;i=nex[i])
{
pa[lb[i]]=max(pa[lb[i]],pa[x]+1);ru[lb[i]]--;
if(ru[lb[i]]==0) q.push(lb[i]);
}
}
for(int i=1;i<=n;i++) ans=max(ans,pa[i]);
printf("%d\n",ans);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(s[j].x>s[i].x && s[j].y>s[i].y && s[j].z>s[i].z)
{add1(i,j+1000,1);add1(j+1000,i,0);}
for(int i=1;i<=n;i++)
{
add1(si,i,1);add1(i,si,0);
add1(i+1000,t,1);add1(t,i+1000,0);
}
printf("%d",n-dinic_());
return 0;
}