nyoj-1084美丽的校园(二) 【线性规划】
2015-07-24 18:02
706 查看
美丽的校园(二)
时间限制: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 3 12 12 12 3 18 0 3 9 1 3 9 2 3 9 3 18 0 0 3 1 3 6 2 6 9 2 3 12 12 12 3 15 0 3 9 1 3 9 2 3 9 3 21 0 0 3 1 3 6 2 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 0x3f3f3f3f using 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; }