nyoj-1084美丽的校园(二) 【线性规划】

来源:互联网 发布:ubuntu 磁盘分区 编辑:程序博客网 时间:2024/04/30 12:10

美丽的校园(二)

时间限制:10000 ms  |  内存限制:65535 KB
难度:5
描述

    来到“lanxiang”专场,当然要问挖掘机技术哪家强了?

    话说既“美丽的校园”之后,树的位置都计算好了,但是要移动先要挖坑啊,于是系领导问Yougth,“挖坑技术哪家强?”,Yougth说“lanxiang很火,但是也需要咱们Acmer的帮助”。

    “lanxiang”有 m 台挖掘机,要在一年n天中挖一些坑,而这期间每台挖掘机都有自己的最小挖掘次数Mi,每一天,有k台挖掘机去执行任务,当天所有挖掘机的最多的挖坑次数为Max,并且这k台挖掘机在这天的最大挖坑个数 r 和最小挖坑个数 l 有限制,即每天的挖掘任务只能在这个限度内,不然就是“lanxiang”也扛不住啊。当然挖的坑越多越好,毕竟系领导也希望早点美化校园,然后让你求n天最多的挖坑数?

    你能帮Yougth解决这个问题吗?

输入
首先两个数 n 和 m (1 <= n <= 365, 1 <= m <= 1000)
然后是一行 m 个值 Mi(0<=Mi<=10000)
然后接着n块,每一块首先两个值 k 和 Max(1 <=k <= 100, 0 <= Max <= 30000)
接着k行每行三个值num,l,r(0 <= num < m, 0 <= l <= r <= 100)
输出
如果不能满足题目的条件的话输出“-1”
否则首先输出最多的挖坑数目
每组数据后面输出一个空行。
样例输入
2 312 12 123 180 3 91 3 92 3 93 180 0 31 3 62 6 92 312 12 123 150 3 91 3 92 3 93 210 0 31 3 62 6 12
样例输出
36-1

上下界网络流解线性规划题

如下建立有上下界网络流的模型。


对于每个挖掘机都有M最小挖坑次数下界的限制,每一天都有最大挖坑次数的上界限制。m->n 的边就表示当天该编号机器的 l最小挖坑次数,r最大挖坑次数的限制。所以对此图求可行流验证是否有解。再求最大流求出解的最大值。

上下界的网络流的讲解链接:http://blog.csdn.net/water_glass/article/details/6823741

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <queue>#include <vector>#define Max_N 800#define Max_M 2100#define Max_size 3000#define inf 0x3f3f3f3fusing namespace std;struct Edge{int to,flow,rev;};struct node{int num,l,r;};int n,m;int dist[Max_size];int iter[Max_size];//bool vis[Max_size];int M[Max_M];int sum_M;int sum_l;int Max[Max_N];vector<Edge> g[Max_size];vector<node> day[Max_N];void init(){int i;sum_M=0;sum_l=0;for(i=0;i<n+m+20;i++){g[i].clear();}for(i=0;i<n+10;i++)day[i].clear();}int find_min(int a,int b){return a>b?b:a;}int find_max(int a,int b){return a>b?a:b;}void add_edge(int from,int to,int c){g[from].push_back((Edge){to,c,g[to].size()});g[to].push_back((Edge){from,0,g[from].size()-1});}void bfs(int s){memset(dist,-1,sizeof(dist));queue<int> que;dist[s]=0;que.push(s);while(!que.empty()){int v=que.front();que.pop();for(int i=0;i<g[v].size();i++){Edge &e=g[v][i];//if(v==0)//printf("to: %d flow:%d dist[e.to]:%d\n", e.to,e.flow,dist[e.to]);if(e.flow>0&&dist[e.to]<0){dist[e.to]=dist[v]+1;que.push(e.to);}}}}int dfs(int v,int t,int f){if(v==t)return f;for(int &i=iter[v];i<g[v].size();i++){Edge &e=g[v][i];if(e.flow>0&&dist[v]<dist[e.to]){int d =dfs(e.to,t,find_min(f,e.flow));if(d>0){e.flow-=d;g[e.to][e.rev].flow+=d;return d;}}}return 0;}int solve(int s,int t){int res=0;for(;;){bfs(s);if(dist[t]<0) {return res;}memset(iter,0,sizeof(iter));int f;while((f=dfs(s,t,inf))>0)res+=f;}}bool judge(int s,int t){if(solve(s,t)==sum_l+sum_M)return true;else return false;}void create_edge(int s,int t){int i,j;int S=n+m+2,T=n+m+3;for(i=1;i<=m;i++){add_edge(s,T,M[i]);add_edge(S,i,M[i]);}for(i=1;i<=n;i++){for(j=0;j<day[i].size();j++){node q=day[i][j];add_edge(q.num,T,q.l);add_edge(S,m+i,q.l);}}add_edge(t,s,inf);}void clear_edge(int s,int t){int S=n+m+2,T=n+m+3;add_edge(S,s,inf);add_edge(t,T,inf);}int main(){int i,j;int k;while(~scanf("%d%d",&n,&m)){init();for(i=1;i<=m;i++){scanf("%d",&M[i]);sum_M+=M[i];add_edge(0,i,inf);}node p;for(i=1;i<=n;i++){scanf("%d%d",&k,&Max[i]);for(j=0;j<k;j++){scanf("%d%d%d",&p.num,&p.l,&p.r);sum_l+=p.l;p.num+=1;day[i].push_back(p);add_edge(p.num,m+i,p.r-p.l);}add_edge(m+i,m+n+1,Max[i]);}int S=n+m+2,T=n+m+3;create_edge(0,n+m+1);if(!judge(S,T)){printf("-1\n");printf("\n");continue;}clear_edge(0,n+m+1);int ans=0;//printf("%d %d \n",sum_l,sum_M);ans+=solve(S,T);printf("%d\n",ans);printf("\n");}return 0;}


0 0