BZOJ 1061 [Noi2008]志愿者招募
题解:
线性规划转网络流
再次提醒自己别把变量的范围搞混了

然后用等式代表点,变量代表边,常量代表最终流向t还是由s流入,跑最小费用最大流
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=1009;
const int maxm=10009;
const int oo=1000000000;
int n,m;
int be[maxm],en[maxm],co[maxm];
struct Edge{
int from,to,cap,flow,cost;
};
vector<int>G[maxn];
vector<Edge>edges;
void Addedge(int x,int y,int z,int w){
// cout<<x<<' '<<y<<endl;
Edge e;
e.from=x;e.to=y;e.cap=z;e.flow=0;e.cost=w;
edges.push_back(e);
e.from=y;e.to=x;e.cap=0;e.flow=0;e.cost=-w;
edges.push_back(e);
int c=edges.size();
G[x].push_back(c-2);
G[y].push_back(c-1);
}
int s,t,totn;
int inq[maxn];
int d[maxn];
int pre[maxn];
queue<int>q;
int Spfa(int &nowflow,int &nowcost){
for(int i=1;i<=totn;++i){
inq[i]=0;d[i]=oo;
}
d[s]=0;inq[s]=1;q.push(s);
while(!q.empty()){
int x=q.front();q.pop();inq[x]=0;
for(int i=0;i<G[x].size();++i){
Edge e=edges[G[x][i]];
if((e.cap>e.flow)&&(d[x]+e.cost<d[e.to])){
d[e.to]=d[x]+e.cost;
pre[e.to]=G[x][i];
if(!inq[e.to]){
inq[e.to]=1;
q.push(e.to);
}
}
}
}
if(d[t]==oo)return 0;
int x=t,f=oo;
while(x!=s){
Edge e=edges[pre[x]];
f=min(f,e.cap-e.flow);
x=e.from;
}
nowflow+=f;nowcost+=f*d[t];
x=t;
while(x!=s){
edges[pre[x]].flow+=f;
edges[pre[x]^1].flow-=f;
x=edges[pre[x]].from;
}
return 1;
}
int Mincost(){
int flow=0,cost=0;
while(Spfa(flow,cost)){
}
return cost;
}
int a[maxn][maxm];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%d",&a[i][m+1]);
for(int i=1;i<=m;++i)scanf("%d%d%d",&be[i],&en[i],&co[i]);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
if((be[j]<=i)&&(en[j]>=i))a[i][j]=1;
}
}
// for(int i=1;i<=n+1;++i){
// for(int j=1;j<=m+1;++j){
// cout<<a[i][j]<<' ';
// }
// cout<<endl;
// }
// cout<<"eating shit"<<endl;
for(int i=n+1;i>=1;--i){
for(int j=1;j<=m+1;++j){
a[i][j]=a[i][j]-a[i-1][j];
}
}
// for(int i=1;i<=n+1;++i){
// for(int j=1;j<=m+1;++j){
// cout<<a[i][j]<<' ';
// }
// cout<<endl;
// }
totn=n+1;s=++totn;t=++totn;
for(int i=1;i<=n+1;++i){
if(i>1)Addedge(i,i-1,oo,0);
if(a[i][m+1]>0)Addedge(s,i,a[i][m+1],0);
else Addedge(i,t,-a[i][m+1],0);
}
for(int j=1;j<=m;++j){
int p1=0,p2=0;
for(int i=1;i<=n+1;++i){
if(a[i][j]==1){
p1=i;break;
}
}
for(int i=n+1;i>=1;--i){
if(a[i][j]==-1){
p2=i;break;
}
}
Addedge(p1,p2,oo,co[j]);
}
cout<<Mincost()<<endl;
return 0;
}
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!

浙公网安备 33010602011771号