CEOI2008 order
2017-07-30 12:30
267 查看
申请了博客不发点东西总觉得不太好
虽然这个题是CEOI的题,但是时间有点久远,现在看来是一道网络流很好的练手题。
透过现象看本质,我们可以发现,每台机器只有租或者买两个选项,且只能二选一,这种二选一,每种选择还有不同权值的东西,我们可以大胆猜测是要求最小割,然后手动画图手玩一下就会发现果然没错。
然后就是建图,网络流的题一般来说只要找到建图的方法,剩下的就是无脑套板子了,所以我们需要思考建图方案。而这对于本蒟蒻来说,简直困难到炸(适当装弱有益健康)。
源点向所有工作连边,权值为收益;工作向机器连边,权值为租用费用;机器向汇点连边,权值为购买费用。
剩下的就是最小割板子了。
(吐槽一下当初我看的那一篇讲dinic的文章,附的板子奇慢无比。。。水题都会T,我还以为是我自带巨大常数(虽然确实我自带巨大常数)。。。)
附带相关格式样例
输入格式:
第一行两个整数,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
虽然这个题是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
相关文章推荐
- 1391: [Ceoi2008]order 最大权闭合图 最小割
- bzoj1391 [Ceoi2008]order
- 1391: [Ceoi2008]order|网络流
- CEOI 2008 order 另类最大权闭合图-可以有依赖违反代价
- BZOJ 1391|CEOI 2008|Order|最小割
- [Luogu4177][CEOI2008]order
- bzoj1391 [Ceoi2008]order
- BZOJ1391: [Ceoi2008]order
- BZOJ1391 [Ceoi2008]order 最小割
- BZOJ 1391: [Ceoi2008]order [最小割]
- bzoj1391 [Ceoi2008]order 网络流——最大权闭合子图
- [CEOI2008]order
- BZOJ1391: [Ceoi2008]order 最大权闭合子图
- 【BZOJ】【1391】【CEOI2008】order
- 1391: [Ceoi2008]order
- 【bzoj1391】[Ceoi2008]order 网络流最小割
- 【bzoj1391】【Ceoi2008】【Order】【最小割】
- [CEOI2008]order
- 【CEOI2008】bzoj1391 order
- BZOJ1391: [Ceoi2008]order