题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。
敌国的导弹形成了立体打击,每个导弹可以抽象成一个三维空间中的点(x; y; z)。拦截系统发射的炮弹也很好地应对了这种情况,每一发炮弹也可以视为一个三维空间中的点。
但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达三维空间中任意的点,但是以后每一发炮弹到达点的坐标(x; y; z) 的三个坐标值都必须大于前一发炮弹的对应坐标值。
某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹飞来的坐标,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。注意: 所有导弹都是同时飞来的
思路
orz人生导师jpwang
前一问一个dp,f[i]表示拦截第i个可以拦截最多拦截到的导弹
f[i] = 1
f[i] = max(f[j]+1) (1 <= j < i) 且受题目限制 来考虑第二问 我们可以将i拆点为 i, i', 对于两个导弹i,j,若从i可以打j,那么我们就连一条(i,j')的边 这样就变成了一个二分图,因为我们要将全部点都达到,所以就是求一个二分图的最小路径覆盖 = 点数 - 最大匹配 跑网络流或其他算法都可以
#include <stdio.h>
#include <queue>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
#define max(x, y) (x) > (y) ? (x) : (y)
#define min(x, y) (x) < (y) ? (x) : (y)
#define INF 0x7f7f7f7f
#define fill(x, y) memset(x, y, sizeof(x))
struct edge
{
int x, y, z;
}e[2000001];
struct arr
{
int to, w, next;
}e1[2000001];
int n, f[10001], ls[20001], cur[20001], state[20001], S, E;
inline int read()
{
int x=0,p=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-')p=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*p;
}
int cmp(edge a, edge b)
{
return a.x < b.x ;
}
int maxE = 1;
int add(int x, int y, int w)
{
e1[++maxE] = (arr) {y, w, ls[x]};
ls[x] = maxE;
e1[++maxE] = (arr) {x, 0, ls[y]};
ls[y] = maxE;
}
int bfs(int S, int E)
{
queue<int> t;
fill(state, 0);
t.push(S);
state[S] = 1;
while (!t.empty())
{
int now = t.front();
t.pop();
for (int i = ls[now]; i; i = e1[i].next)
{
if (e1[i].w > 0 && !state[e1[i].to])
{
state[e1[i].to] = state[now] + 1;
t.push(e1[i].to);
if (e1[i].to == E)
return true;
}
}
}
return false;
}
int find(int now, int mn)
{
if (!mn || now == E)
return mn;
int ret = 0;
for (int &i = cur[now]; i; i = e1[i].next)
if (state[now] + 1 == state[e1[i].to] && e1[i].w > 0)
{
int d = find(e1[i].to, min(e1[i].w, mn - ret));
e1[i].w -= d;
e1[i^1].w += d;
ret += d;
if (ret == mn) break;
}
return ret;
}
int dinic()
{
int ans = 0;
while (bfs(S, E))
{
for (int i = S; i <= E; i++)
cur[i] = ls[i];
ans += find(S, INF);
}
return ans;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
e[i].x = read();
e[i].y = read();
e[i].z = read();
}
sort(e + 1, e + n + 1, cmp);
for (int i = 1; i <= n; i++)
{
f[i] = 1;
for (int j = 1; j < i; j++)
{
if (e[j].x < e[i].x && e[j].y < e[i].y && e[j].z < e[i].z)
f[i] = max(f[i], f[j] + 1);
}
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
ans = max(ans, f[i]);
}
printf("%d\n", ans);
int l = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j < i; j++)
if (e[j].x < e[i].x && e[j].y < e[i].y && e[j].z < e[i].z)
add(j, i + n, 1);
S = 0;
E = n * 2 + 1;
for (int i = 1; i <= n; i++)
{
add(S, i, 1);
add(i + n, E, 1);
}
printf("%d", n - dinic());
}
Comments NOTHING