首页 > 代码库 > bzoj1930

bzoj1930

1930: [Shoi2003]pacman 吃豆豆

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1923  Solved: 435
[Submit][Status][Discuss]

Description

两个PACMAN吃豆豆。一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方。PACMAN走到豆豆处就会吃掉它。PACMAN行走的路线很奇怪,只能向右走或者向上走,他们行走的路线不可以相交。 请你帮这两个PACMAN计算一下,他们俩加起来最多能吃掉多少豆豆。

Input

第一行为一个整数N,表示豆豆的数目。 接下来 N 行,每行一对正整数,表示第i个豆豆的坐标。任意两个豆豆的坐标都不会重合。

Output

仅有一行包含一个整数,即两个PACMAN加起来最多能吃掉的豆豆数量

Sample Input

8

8 1

1 5

5 7

2 2

7 8

4 6

3 3

6 4

Sample Output

7

HINT

技术分享 

N < = 2000

Source

666 卡内存,zky大神只用了2000kb

很容易想出这是个最大费用流。但是很明显,2000*2000的边很容易tle,那么我们要进行剪枝。如果a->b,b->c,那么a->c是没有必要的。

但是还卡空间,因此我们可以用short。。。 连边:s:原点 ss:原点拆开的点,t:汇点

link(s,ss,f=2,c=0) for each i link(ss,i,f=2,c=0) link(i+n(拆点),t,f=2,c=0)

每个点和可以到达的点:link(i+n,j,f=1,c=1) link(i+n,j,f=1,c=1) 并且我们先按x排序,从x小到大枚举,如果当前的y比之前最小值要大,那么肯定之前连过,不用连了。

技术分享
#include<bits/stdc++.h>  
using namespace std;
#define inf (1<<30)
#define N 2010
struct edge
{
    short f,c,to;
    int nxt;
}e[4500010];
struct data
{
    int x,y;
}x[4010];
int cnt=1,s,t,ss,n;
int pree[4010],prev[4010],dist[4010],head[4010];
short q[4200010];
inline bool cp(data x,data y)
{
    if(x.x!=y.x) return x.x<y.x;
    return x.y<y.y;
}
inline int min(int x,int y)
{
    return x<y?x:y;
}
inline void link(int u,int v,int f,int c)
{
    e[++cnt].nxt=head[u];
    head[u]=cnt;
    e[cnt].to=v;
    e[cnt].f=f;
    e[cnt].c=c;
}
inline void ins(int u,int v,int c,int f)
{
    link(u,v,f,c);  link(v,u,0,-c);
}
inline bool spfa()
{
    memset(dist,-1,sizeof(dist));
    int l=1,r=0;
    q[++r]=s; dist[s]=0;
    while(l<=r)
    {
        int u=q[l++]; 
        for(int i=head[u];i;i=e[i].nxt) if(e[i].f&&dist[e[i].to]<dist[u]+e[i].c)
        {
            prev[e[i].to]=u;
            pree[e[i].to]=i;
            dist[e[i].to]=dist[u]+e[i].c;
            q[++r]=e[i].to;
        }
    }
    return dist[t]!=-1;
}
inline int flow()
{
    int u=t,delta=inf;
    while(u!=s)
    {
        delta=min(delta,e[pree[u]].f);
        u=prev[u];
    }
    u=t;
    while(u!=s)
    {
        e[pree[u]].f-=delta;
        e[pree[u]^1].f+=delta;
        u=prev[u];
    }
    return dist[t]*delta;
}
inline void MinCostFlow()
{
    int ans=0,cur=0;
    while(spfa())
    {
        cur+=flow();
        if(cur>ans) ans=cur;
    }
    printf("%d\n",ans);
}
int main()
{
    scanf("%d",&n); s=2*n+1; t=2*n+2; ss=s+2; 
    for(int i=1;i<=n;i++) scanf("%d%d",&x[i].x,&x[i].y);
    ins(s,ss,0,2);
    for(int i=1;i<=n;i++)
    {
        ins(ss,i,0,2);
        ins(i+n,t,0,2);
    } 
    sort(x+1,x+n+1,cp);
    for(int i=1;i<=n;i++)
    {
        ins(i,i+n,1,1);
        ins(i,i+n,0,1);
        int top=inf;
        for(int j=i+1;j<=n;j++)
            if(x[j].y<top&&x[i].y<=x[j].y) 
                ins(i+n,j,0,2),top=x[j].y;
    }
    MinCostFlow();
    return 0;
} 
View Code

 

bzoj1930