洛谷 P2488 [SDOI2011]工作安排

题目描述

你的任务是制定出一个产品的分配方案,使得订单条件被满足,并且所有员工的愤怒值之和最小。由于我们并不想使用Special Judge,也为了使选手有更多的时间研究其他两道题目,你只需要输出最小的愤怒值之和就可以了。

输入输出格式

输入格式:

输出格式:

仅输出一个整数,表示最小的愤怒值之和。

输入输出样例

输入样例#1:

2 3
2 2 2
1 1 0
0 0 1
1
2
1 10
1
2
1 6

输出样例#1:

24

说明

一看,哇,修车,美食节,直接拆点,跑费用流,光荣T掉,还WA了几个点(原因不明)

然而这个题和修车不一样,每一份流量的性质都是相同的,没有拆点的必要,直接拆边就好了

SS--(C[i],0)-->物品i--(INF,0)-->员工j---(S[j][k]-s[j][k-1],W[i][j])-->TT

把每个员工到TT的边拆成S[i]+1条即可

  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <string>
  6 #include <cstring>
  7 #include <cmath>
  8 #include <map>
  9 #include <stack>
 10 #include <set>
 11 #include <vector>
 12 #include <queue>
 13 #include <time.h>
 14 #define eps 1e-7
 15 #define INF 0x3f3f3f3f
 16 #define MOD 1000000007
 17 #define rep0(j,n) for(int j=0;j<n;++j)
 18 #define rep1(j,n) for(int j=1;j<=n;++j)
 19 #define pb push_back
 20 #define set0(n) memset(n,0,sizeof(n))
 21 #define ll long long
 22 #define ull unsigned long long
 23 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt)
 24 #define max(a,b) (a>b?a:b)
 25 #define min(a,b) (a<b?a:b)
 26 #define print_runtime printf("Running time:%.3lfs\n",double(clock())/1000.0)
 27 #define TO(j) printf(#j": %d\n",j);
 28 //#define OJ
 29 using namespace std;
 30 const int MAXINT = 100010;
 31 const int MAXNODE = 700;
 32 const int MAXEDGE = 1000000;
 33 char BUF,*buf;
 34 int read(){
 35     char c=getchar();int f=1,x=0;
 36     while(!isdigit(c)){if(c==‘-‘) f=-1;c=getchar();}
 37     while(isdigit(c)){x=x*10+c-‘0‘;c=getchar();}
 38     return f*x;
 39 }
 40 char get_ch(){
 41     char c=getchar();
 42     while(!isalpha(c)) c=getchar();
 43     return c;
 44 }
 45 //------------------- Head Files ----------------------//
 46 int cnt,dis[MAXNODE],q[MAXNODE*MAXNODE],inq[MAXNODE],n,m,C[300],ok[300][300],S[300],T[300][7],W[300][7],SS,TT;
 47 struct edge{
 48     int u,v,c,cost;
 49     edge *nxt;
 50     edge(){}
 51     edge(int _u,int _v,int _c,int _cost,edge *_nxt):u(_u),v(_v),c(_c),cost(_cost),nxt(_nxt){}
 52 }mp[MAXEDGE],*head[MAXNODE],*from[MAXNODE];
 53 void addedge(int u,int v,int c,int cost){
 54     mp[cnt]=edge(u,v,c,cost,head[u]);
 55     head[u]=&mp[cnt++];
 56     mp[cnt]=edge(v,u,0,-cost,head[v]);
 57     head[v]=&mp[cnt++];
 58 }
 59 int spfa(int ss,int tt){
 60     memset(dis,INF,sizeof(dis));
 61     dis[ss]=0;
 62     int *h,*t;
 63     h=t=q;
 64     *t++=ss;
 65     while(h!=t){
 66         int p=*h++;
 67         inq[p]=0;
 68         iter(i,p){
 69             if(i->c&&dis[i->v]>dis[p]+i->cost){
 70                 dis[i->v] = dis[p]+i->cost;
 71                 from[i->v]=i;
 72                 if(!inq[i->v]){
 73                     *t++=i->v;
 74                     inq[i->v]=1;
 75                 }
 76             }
 77         }
 78     }
 79     return dis[tt]!=INF;
 80 }
 81 edge *rev(edge *e){
 82     return &mp[(e-mp)^1];
 83 }
 84 ll extend(int ss,int tt){
 85     ll c=INF,cost=0;
 86     int p=tt;
 87     while(p!=ss){
 88         c=min(c,from[p]->c);
 89         cost+=from[p]->cost;
 90         p=from[p]->u;
 91     }
 92     p=tt;
 93     while(p!=ss){
 94         from[p]->c-=c;
 95         rev(from[p])->c+=c;
 96         p=from[p]->u;
 97     }
 98     return c*cost;
 99 }
100 ll cost_flow(int ss,int tt){
101     ll ans=0;
102     while(spfa(ss,tt)){
103         ans+=extend(ss,tt);
104     }
105     return ans;
106 }
107 void get_input();
108 void work();
109 int main() {
110     get_input();
111     work();
112     return 0;
113 }
114 void work(){
115     SS=698;TT=699;
116     rep0(i,n){
117         addedge(SS,i,C[i],0);
118         rep0(j,m) if(ok[j][i]) addedge(i,n+j,INF,0);
119     }
120     rep0(i,m){
121         if(S[i]==0){
122             addedge(n+i,TT,INF,W[i][0]);
123         }else{
124             addedge(n+i,TT,T[i][0],W[i][0]);
125             for(int j=1;j<S[i];j++){
126                 addedge(n+i,TT,T[i][j]-T[i][j-1],W[i][j]);
127             }
128             addedge(n+i,TT,INF,W[i][S[i]]);
129         }
130     }
131     printf("%lld\n",cost_flow(SS,TT));
132 }
133 void get_input(){
134     m=read();n=read();
135     rep0(i,n) C[i]=read();
136     rep0(i,m) rep0(j,n) ok[i][j]=read();
137     rep0(i,m){
138         S[i]=read();
139         rep0(j,S[i]) T[i][j]=read();
140         rep0(j,S[i]+1) W[i][j]=read();
141     }
142 }
143 /*
144 2 3
145 2 2 2
146 1 1 0
147 0 0 1
148 1
149 2
150 1 10
151 1
152 2
153 1 6
154 */
时间: 2024-08-13 04:31:33

洛谷 P2488 [SDOI2011]工作安排的相关文章

P2488 [SDOI2011]工作安排 费用流

\(\color{#0066ff}{ 题目描述 }\) 你的任务是制定出一个产品的分配方案,使得订单条件被满足,并且所有员工的愤怒值之和最小.由于我们并不想使用Special Judge,也为了使选手有更多的时间研究其他两道题目,你只需要输出最小的愤怒值之和就可以了. \(\color{#0066ff}{输入格式}\) \(\color{#0066ff}{输出格式}\) 仅输出一个整数,表示最小的愤怒值之和. \(\color{#0066ff}{输入样例}\) 2 3 2 2 2 1 1 0 0

【BZOJ2245】[SDOI2011]工作安排 拆边费用流

[BZOJ2245][SDOI2011]工作安排 Description 你的公司接到了一批订单.订单要求你的公司提供n类产品,产品被编号为1~n,其中第i类产品共需要Ci件.公司共有m名员工,员工被编号为1~m员工能够制造的产品种类有所区别.一件产品必须完整地由一名员工制造,不可以由某名员工制造一部分配件后,再转交给另外一名员工继续进行制造. 我们用一个由0和1组成的m*n的矩阵A来描述每名员工能够制造哪些产品.矩阵的行和列分别被编号为1~m和1~n,Ai,j为1表示员工i能够制造产品j,为0

bzoj 2245: [SDOI2011]工作安排(费用流)

2245: [SDOI2011]工作安排 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 1446  Solved: 692 [Submit][Status][Discuss] Description 你的公司接到了一批订单.订单要求你的公司提供n类产品,产品被编号为1~n,其中第i类产品共需要Ci件.公司共有m名员工,员工被编号为1~m员工能够制造的产品种类有所区别.一件产品必须完整地由一名员工制造,不可以由某名员工制造一部分配件后,再转交给另

【BZOJ 2245】[SDOI2011]工作安排

Description 你的公司接到了一批订单.订单要求你的公司提供n类产品,产品被编号为1~n,其中第i类产品共需要Ci件.公司共有m名员工,员工被编号为1~m员工能够制造的产品种类有所区别.一件产品必须完整地由一名员工制造,不可以由某名员工制造一部分配件后,再转交给另外一名员工继续进行制造. 我们用一个由0和1组成的m*n的矩阵A来描述每名员工能够制造哪些产品.矩阵的行和列分别被编号为1~m和1~n,Ai,j为1表示员工i能够制造产品j,为0表示员工i不能制造产品j. 如 果公司分配了过多工

【bzoj2245】[SDOI2011]工作安排 费用流

题目描述 你的公司接到了一批订单.订单要求你的公司提供n类产品,产品被编号为1~n,其中第i类产品共需要Ci件.公司共有m名员工,员工被编号为1~m员工能够制造的产品种类有所区别.一件产品必须完整地由一名员工制造,不可以由某名员工制造一部分配件后,再转交给另外一名员工继续进行制造. 我们用一个由0和1组成的m*n的矩阵A来描述每名员工能够制造哪些产品.矩阵的行和列分别被编号为1~m和1~n,Ai,j为1表示员工i能够制造产品j,为0表示员工i不能制造产品j. 如果公司分配了过多工作给一名员工,这

[SDOI2011]工作安排

Description 你的公司接到了一批订单.订单要求你的公司提供n类产品,产品被编号为1~n,其中第i类产品共需要Ci件.公司共有m名员工,员工被编号为1~m员工能够制造的产品种类有所区别.一件产品必须完整地由一名员工制造,不可以由某名员工制造一部分配件后,再转交给另外一名员工继续进行制造. 我们用一个由0和1组成的m*n的矩阵A来描述每名员工能够制造哪些产品.矩阵的行和列分别被编号为1~m和1~n,Ai,j为1表示员工i能够制造产品j,为0表示员工i不能制造产品j. 如果公司分配了过多工作

BZOJ2245 [SDOI2011]工作安排 【费用流】

题目 你的公司接到了一批订单.订单要求你的公司提供n类产品,产品被编号为1~n,其中第i类产品共需要Ci件.公司共有m名员工,员工被编号为1~m员工能够制造的产品种类有所区别.一件产品必须完整地由一名员工制造,不可以由某名员工制造一部分配件后,再转交给另外一名员工继续进行制造. 我们用一个由0和1组成的m*n的矩阵A来描述每名员工能够制造哪些产品.矩阵的行和列分别被编号为1~m和1~n,Ai,j为1表示员工i能够制造产品j,为0表示员工i不能制造产品j. 如果公司分配了过多工作给一名员工,这名员

洛谷 P2486 [SDOI2011]染色

题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例#1: 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q 3 5 C 5 1 2 Q 3 5 输出样例#1: 3 1 2 说明 题目大意:给一棵树,要求支持链覆盖+查询链上颜色段数 先考虑链上怎么做吧,颜色段数这个东西支持区间加,一个区间可以用三个属性表示:左端点的颜色,右端点的颜色,区间颜色段数 两段合并以后的颜色段数是:左段颜色段数+右

bzoj 2245: [SDOI2011]工作安排

1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define M 10000 5 #define inf 2139062143 6 using namespace std; 7 int cnt=1,n,m,T,d[M],q[2*M],f[M],head[M],next[10*M],u[10*M],v[10*M],w[10*M],fro[10*M],fr[M]; 8 int mp[100]; 9