「BZOJ2879」[Noi2012]美食节

这道题就是 「BZOJ1070」[SCOI2007]修车 的加强版

如果一开始把全部边连上会T

优化的方法是只连用到过和下一次增广可能用到的边。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=50,M=110,NN=100010,oo=1e9;
 4 int n,m,cost[N][M],tot,s,t,p[N],rank[NN],c[NN];
 5 bool isend[NN];
 6 struct Edge{
 7     int from,to,flow,cap,w;
 8 };
 9 int edge_tot;
10 vector<Edge>edge;
11 vector<int>point[NN];
12 void add_edge(int f,int t,int cc,int ww){
13     edge.push_back((Edge){f,t,0,cc,ww});
14     point[f].push_back(edge_tot++);
15     edge.push_back((Edge){t,f,0,0,-ww});
16     point[t].push_back(edge_tot++);
17     return;
18 }
19 int dis[NN],pre[NN];
20 bool inq[NN];
21 bool spfa(){
22     queue<int>q;
23     int x;
24     for(int i=1;i<=tot;i++) dis[i]=oo;
25     q.push(s);
26     dis[s]=0,inq[s]=1;
27     while(!q.empty()){
28         x=q.front();q.pop();
29         inq[x]=0;
30         for(int i=0;i<point[x].size();i++){
31             Edge& e=edge[point[x][i]];
32             if(e.cap<=e.flow) continue;
33             if(dis[x]+e.w<dis[e.to]){
34                 dis[e.to]=dis[x]+e.w,pre[e.to]=point[x][i];
35                 if(!inq[e.to]){inq[e.to]=1;q.push(e.to);}
36             }
37         }
38     }
39     return dis[t]<oo;
40 }
41 int mincostmaxflow(){
42     int ans=0,f,now;
43     while(spfa()){
44         f=oo,now=t;
45         while(now!=s){
46             f=min(f,edge[pre[now]].cap-edge[pre[now]].flow);
47             if(isend[now]){
48                 isend[now]=0,isend[++tot]=1,rank[tot]=rank[now]+1,c[tot]=c[now];
49                 add_edge(tot,t,1,0);
50                 for(int i=3;i<=n+2;i++) add_edge(i,tot,1,rank[tot]*cost[i-2][c[tot]]);
51             }
52             now=edge[pre[now]].from;
53         }
54         ans+=dis[t]*f,now=t;
55         while(now!=s){
56             edge[pre[now]].flow+=f,edge[pre[now]^1].flow-=f;
57             now=edge[pre[now]].from;
58         }
59     }
60     return ans;
61 }
62 int main(){
63     scanf("%d%d",&n,&m);
64     for(int i=1;i<=n;i++) scanf("%d",&p[i]);
65     for(int i=1;i<=n;i++)
66         for(int j=1;j<=m;j++)scanf("%d",&cost[i][j]);
67     s=++tot,t=++tot;
68     for(int i=1;i<=n;i++) add_edge(s,++tot,p[i],0);
69     for(int i=1;i<=m;i++){
70         add_edge(++tot,t,1,0);
71         rank[tot]=1,c[tot]=i,isend[tot]=1;
72         for(int j=3;j<=n+2;j++) add_edge(j,i+n+2,1,cost[j-2][i]);
73     }
74     int ans=mincostmaxflow();
75     printf("%d",ans);
76 }

 

posted @ 2018-03-08 15:43  Cupcake  阅读(86)  评论(0编辑  收藏  举报