[BZOJ1061][Noi2008]志愿者招募 线性规划+费用流

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1061

根据题意列方程,然后用网络流解线性规划。

题解直接贴ByVoid的吧,太神了:https://www.byvoid.com/blog/noi-2008-employee/

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 const int INF=1<<30;
 7 int inline readint(){
 8     int Num;char ch;
 9     while((ch=getchar())<'0'||ch>'9');Num=ch-'0';
10     while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0';
11     return Num;
12 }
13 int n,m;
14 int A[1010];
15 int S,T;
16 int to[30000],ne[30000],w[30000],c[30000],fir[1010],cnt=0;
17 void add(int a,int b,int x,int y=INF){
18     to[cnt]=b,w[cnt]=x,c[cnt]=y,ne[cnt]=fir[a],fir[a]=cnt++;
19     to[cnt]=a,w[cnt]=-x,c[cnt]=0,ne[cnt]=fir[b],fir[b]=cnt++;
20 }
21 int dis[1010],pre[1010];
22 bool in[1010];
23 queue <int> q;
24 bool Spfa(){
25     memset(dis,127/3,sizeof(dis));
26     q.push(S);
27     in[S]=true;
28     dis[S]=0;
29     int u;
30     while(!q.empty()){
31         u=q.front();
32         q.pop();
33         in[u]=false;
34         for(int i=fir[u];i!=-1;i=ne[i]){
35             int v=to[i];
36             if(dis[v]>dis[u]+w[i]&&c[i]){
37                 dis[v]=dis[u]+w[i];
38                 pre[v]=i;
39                 if(!in[v]){
40                     q.push(v);
41                     in[v]=true;
42                 }
43             }
44         }
45     }
46     return dis[T]!=dis[0];
47 }
48 void Mcmf(){
49     int cost=0;
50     pre[S]=-1;
51     while(Spfa()){
52         int f=INF;
53         for(int i=pre[T];i!=-1;i=pre[to[i^1]]) f=min(f,c[i]);
54         for(int i=pre[T];i!=-1;i=pre[to[i^1]]){
55             c[i]-=f;
56             c[i^1]+=f;
57         }
58         cost+=dis[T]*f;
59     }
60     printf("%d\n",cost);
61 }
62 int main(){
63     n=readint();
64     m=readint();
65     for(int i=1;i<=n;i++) A[i]=readint();
66     memset(fir,-1,sizeof(fir));
67     S=n+2;
68     T=n+3;
69     for(int i=1;i<=n+1;i++){
70         if(A[i]>=A[i-1]) add(S,i,0,A[i]-A[i-1]);
71         else add(i,T,0,A[i-1]-A[i]);
72         if(i>1) add(i,i-1,0);
73     }
74     for(int i=1;i<=m;i++){
75         int a=readint(),
76             b=readint(),
77             c=readint();
78         add(a,b+1,c);
79     }
80     Mcmf();
81     return 0;
82 }

 

posted @ 2017-09-19 17:46  halfrot  阅读(205)  评论(0编辑  收藏  举报