zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    roundabout插件使用(3d旋转轮播图)兼容IE8
    css实现定高的元素在不定高的容器中水平垂直居中(兼容IE8及以上)
    jq点击小图 弹出大图(更新版)
    pc端页面在移动端显示问题
    swiper横向轮播--3d
    swiper横向轮播(兼容IE8)
    windows 7安装apache
    从SDP中至少要看到那些东西?
    FS拓展设置
    Freeswitch 入门
  • 原文地址:https://www.cnblogs.com/zzyer/p/8566329.html
Copyright © 2011-2022 走看看