您的位置:首页 > 其它

CEOI2008 order

2017-07-30 12:30 267 查看
申请了博客不发点东西总觉得不太好

虽然这个题是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
,dis
,que
;
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: