CEOI2008 order
申请了博客不发点东西总觉得不太好
虽然这个题是CEOI的题,但是时间有点久远,现在看来是一道网络流很好的练手题。
透过现象看本质,我们可以发现,每台机器只有租或者买两个选项,且只能二选一,这种二选一,每种选择还有不同权值的东西,我们可以大胆猜测是要求最小割,然后手动画图手玩一下就会发现果然没错。
然后就是建图,网络流的题一般来说只要找到建图的方法,剩下的就是无脑套板子了,所以我们需要思考建图方案。而这对于本蒟蒻来说,简直困难到炸(适当装弱有益健康)。
源点向所有工作连边,权值为收益;工作向机器连边,权值为租用费用;机器向汇点连边,权值为购买费用。
剩下的就是最小割板子了。
(吐槽一下当初我看的那一篇讲dinic的文章,附的板子奇慢无比。。。水题都会T,我还以为是我自带巨大常数(虽然确实我自带巨大常数)。。。)
//made by Crazy01
#include<map>
#include<queue>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#define inf 1<<30
#define LL long long
#define c233 cout<<"233"<<endl
#define mem(s) memset(s,0,sizeof(s))
#define M 4500000
#define N 4050
#define il inline
using namespace std;
int nxt[M],t[M],w[M],head[N],dis[N],que[N];
int n,m,maxe=1,S,T,all,hd,tl;
il int min(int x,int y){
return x<y?x:y;
}
il int gi(){
int x=0,res=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();}
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*res;
}
il void build(int a,int b,int c){
nxt[++maxe]=head[a];t[maxe]=b;w[maxe]=c;head[a]=maxe;
nxt[++maxe]=head[b];t[maxe]=a;w[maxe]=0;head[b]=maxe;
}
il void init(){
n=gi();m=gi();
S=0;T=m+n+1;
for(int i=1;i<=n;i++){
int a=gi(),b=gi();
build(S,i,a);
all+=a;
for(int j=1;j<=b;j++){
int x=gi(),y=gi();
build(i,x+n,y);
}
}
for(int i=1;i<=m;i++){
int x=gi();
build(i+n,T,x);
}
}
il bool bfs(){
hd=tl=0;
for(int i=S;i<=T;i++)dis[i]=-1;
dis[S]=0;que[hd]=S;tl++;
while(hd<tl){
int x=que[hd];hd++;
if(x==T)return 1;
for(int i=head[x];i;i=nxt[i]){
int to=t[i],f=w[i];
if(f>0&&dis[to]==-1){
dis[to]=dis[x]+1;
que[tl++]=to;
}
}
}
return 0;
}
il int dfs(int x,int flll){
if(x==T)return flll;
int tag=0;
for(int i=head[x];i;i=nxt[i]){
int to=t[i],f=w[i];
if(dis[to]==dis[x]+1&&f>0){
f=dfs(to,min(flll-tag,f));
tag+=f;
w[i]-=f;w[i^1]+=f;
if(tag==flll)return tag;
}
}
if(tag==0)dis[x]=-1;
return tag;
}
il void dinic(){
while(bfs())all-=dfs(S,inf);
printf("%d\n",all);
}
int main(){
init();
dinic();
return 0;
}
附带相关格式样例
输入格式:
第一行两个整数,n 和 m,分别表示工作数和机器数.
接下来输入分为 n 段,即对于每项工作:
第一行为两个整数,a 和 b,分别为完成该工作的收益和工序数;
接下来 b 行,每行两个整数,x 和 y,分别表示完成该工序需要的机器和机器的租赁费用.
接下来一行有 m 个数, wi 表示购买每台机器的费用.
输出格式:
输出仅一行,即可以获得的最大收益.
输入样例:
5 5
1 3
2 3
3 2
5 5
1 1
2 2
4 1
5 2
4 4
1 4
2 3
3 3
4 2
5 5
1 5
2 3
3 3
4 1
5 5
1 1 1 4 4
输出样例:
5