zoukankan      html  css  js  c++  java
  • P3980 [NOI2008]志愿者招募

    题解

    发现就是一个线性规划。
    我们用 (x_i) 来表示第 (i) 种志愿者的个数, (a_i) 来表示每一天的人数下限。

    [x_o+x_p+...ge a_i\ x_o+x_q+...ge a_{i+1}\ ... ]

    就套路一下,把不等号变成等号。

    [x_o+x_p+...=a_i+c_i\ x_o+x_q+...=a_{i+1}+c_{i+1} ]

    然后可以做一下差,然后发现每一个 (x_o) 只会在等式的左右各出现一次,分别是 (s_a)(t_a+1) 的位置。然后 (c_i) 也是只出现一次,然后就好了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N=1e3+5,M=1e4+5;
    const int INF=1e18+7;
    int n,m,from,to,tot=0;
    int id[N],a[N];
    struct Vol{int s,t,c;}b[M];
    struct Edge{int nxt,to,flow,cost;};vector<Edge> e;int fir[N];
    void add(int u,int v,int x,int y){e.push_back((Edge){fir[u],v,x,y}),fir[u]=e.size()-1;}
    int dis[N],cur[N],res=0;
    queue<int> q;bool vis[N];
    bool spfa(){
    	for(int i=1;i<=tot;++i) dis[i]=INF,cur[i]=fir[i];
    	dis[from]=0,vis[from]=true,q.push(from);
    	while(!q.empty()){
    		int u=q.front();vis[u]=false,q.pop();
    		// printf("%d %d %d
    ",u,dis[u],fir[u]);
    		for(int i=fir[u];i>=0;i=e[i].nxt){
    			// printf("---%d %d %d
    ",e[i].to,e[i].cost,dis[e[i].to]);
    			if(!e[i].flow||dis[e[i].to]<=dis[u]+e[i].cost) continue;
    			dis[e[i].to]=dis[u]+e[i].cost;
    			if(!vis[e[i].to]) vis[e[i].to]=true,q.push(e[i].to);
    		}
    	}
    	return dis[to]!=INF;
    }
    int dfs(int u,int flow){
    	if(u==to) return flow;
    	int res=0;vis[u]=true;
    	for(int i=cur[u];i>=0&&flow;i=e[i].nxt){
    		int v=e[i].to;cur[u]=i;
    		if(!e[i].flow||dis[e[i].to]!=dis[u]+e[i].cost||vis[v]) continue;
    		int tmp=dfs(e[i].to,min(flow,e[i].flow));
    		e[i].flow-=tmp,e[i^1].flow+=tmp,flow-=tmp,res+=tmp;
    	}
    	return vis[u]=false,res;
    }
    signed main(){
    	cin>>n>>m;
    	from=++tot,to=++tot;
    	memset(fir,-1,sizeof(fir)),id[n+1]=++tot;
    	for(int i=1;i<=n;++i) scanf("%lld",&a[i]),id[i]=++tot;
    	for(int i=1;i<=m;++i) scanf("%lld%lld%lld",&b[i].s,&b[i].t,&b[i].c);
    	for(int i=1;i<=n;++i){
    		add(from,id[i+1],a[i],0),add(id[i+1],from,0,0);
    		add(id[i],to,a[i],0),add(to,id[i],0,0);
    		add(id[i],id[i+1],INF,0),add(id[i+1],id[i],0,0);
    	}
    	for(int i=1;i<=m;++i){
    		add(id[b[i].t+1],id[b[i].s],INF,b[i].c);
    		add(id[b[i].s],id[b[i].t+1],0,-b[i].c);
    	}
    	while(spfa()) res+=dis[to]*dfs(from,INF);
    	printf("%lld
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    ASE19团队项目 beta阶段 model组 scrum report list
    ASE19团队项目 beta阶段 model组 scrum7 记录
    ASE19团队项目 beta阶段 model组 scrum6 记录
    ASE19团队项目 beta阶段 model组 scrum5 记录
    ASE19团队项目 beta阶段 model组 scrum4 记录
    ASE19团队项目 beta阶段 model组 scrum3 记录
    ASE19团队项目 beta阶段 model组 scrum2 记录
    ASE19团队项目 beta阶段 model组 scrum1 记录
    【ASE模型组】Hint::neural 模型与case study
    【ASE高级软件工程】第二次结对作业
  • 原文地址:https://www.cnblogs.com/Point-King/p/14353774.html
Copyright © 2011-2022 走看看