[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 }