51nod 1392 装盒子【网络流费用流+特殊判断】
有n个长方形盒子,第i个长度为Li,宽度为Wi,我们需要把他们套放。注意一个盒子只可以套入长和宽分别不小于它的盒子,并且一个盒子里最多只能直接装入另外一个盒子 (但是可以不断嵌套),例如1 * 1 可以套入2 * 1,而2 * 1再套入2 * 2。套入之后盒子占地面积是最外面盒子的占地面积。给定N个盒子大小,求最终最小的总占地面积。
Input
第一行一个数N表示盒子的个数。 接下来N行,每行两个正整数,表示每个盒子的长度和宽度。 所有整数都是正的(N,以及盒子的长宽),且不超过200。
Output
一行一个整数表示最终最小的占地面积。
Input示例
3 1 1 1 2 2 1
Output示例
4
由于答案只计算最大面积的那个值
所以每一次增广路径选出最大面积的那个加起来
在相同情况下 装盒子要装最外层面积大的 而不是总面积大的那个
#include <stdio.h>
#include <bits/stdc++.h>
#define read(); freopen("input.txt","r",stdin);
using namespace std;
typedef long long ll;
class E{
public:
int from,to,c,w,next;
};
class P{
public:
int x,y;
};
int cmp(P a,P b){
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
int cmp1(P a,P b){
return (a.x==b.x && a.y==b.y);
}
E e[100005];
P s[205];
int next[405],in[404],pre[404],dis[404],dism[404];
int n,cnt=1,S=0,T=402,ans;
void add(int from,int to,int w){
e[++cnt].from=from;e[cnt].to=to;e[cnt].c=1;e[cnt].w=w;e[cnt].next=next[from];next[from]=cnt;
e[++cnt].from=to;e[cnt].to=from;e[cnt].c=0;e[cnt].w=-w;e[cnt].next=next[to];next[to]=cnt;
}
int spfa(){
memset(in,0,sizeof(in));
memset(dis,127,sizeof(dis));
memset(dism,127,sizeof(dism));
dis[S]=0;
dism[S]=0;
in[S]=1;
queue<int> q;
q.push(S);
while(q.size()){
int u=q.front();q.pop();in[u]=0;
for(int i=next[u];i;i=e[i].next){
int to=e[i].to;
if(e[i].c&& dis[u]+e[i].w<dis[to]&& (min(e[i].w,dism[u])<dism[to])){ //
dism[to]=min(e[i].w,dism[u]);
dis[to]=dis[u]+e[i].w;
pre[to]=i;
if(in[to]==0)in[to]=1,q.push(to);
}
}
}
if(dis[T]<(1<<28)) return 1;
return 0;
}
void mcf(){
int flag=0;
for(int i=pre[T];i;i=pre[e[i].from]){
e[i].c=0;
e[i^1].c=1;
}
ans+=dism[T];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) cin>>s[i].x>>s[i].y;
sort(s+1,s+1+n,cmp);
n=unique(s+1,s+1+n,cmp1)-s-1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i!=j && s[i].x<=s[j].x && s[i].y<=s[j].y )
add(i+n,j,0);
}
add(i,i+n,-s[i].x*s[i].y);
add(S,i,0);
add(i+n,T,0);
}
while(spfa())mcf();
cout<<-ans<<endl;
return 0;
}