[BZOJ1391]-[Ceoi2008]order-最小割
2018-02-18 21:22
302 查看
说在前面
这题me居然想了快一个小时天呐没救了
题目
BZOJ1391传送门题目大意
有N种机器和M个工作。完成第i个工作会获得a[i]的收益,但是需要其中b[i]个机器的参与才能完成工作(会给出需要的机器的编号)。机器可以租赁(完成不同的任务,租金可能不同),也可以买下来。现在给出所有任务和机器的信息,求出最大获利。N,M不超过1200
单个任务收益不超过5000,机器单价不超过20000
输入输出格式
输入格式:第一行两个整数N,M,含义如题
接下来有N个数据块,每个数据块描述一个工作,格式如下 {
第一行两个整数profit和cnt,表示完成这个工作的获利与所需机器数量
接下来cnt行,每行两个整数id,cost,表示用到了第id台机器,租金cost
}
接下来M行,每行一个整数,表示每个机器的单价
输出格式:
输出最大获利
解法
这道题也是属于 想要获利就得付出代价 类型但是相较于普通的最小割(就是直接S->u->T)有点区别,这道题不仅有获利 和 代价之间有关系,代价也有两种。
然而这其实并没有好害怕的,直接套在一起就可以了
说人话就是,把获利和代价看成一个最小割,代价内部又是一个最小割
于是建出来就是这样:S—获利—>mission—代价—>T
其中,mission到T的代价是一个最小割,即mission—租金—>machine—买下来—>T
(貌似这个还可以推广到更复杂的情况,就是多套几层)
然后这题就做完了
下面是自带大常数的代码
不加当前弧优化还过不去…#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; int N , M , tp = 1 , head[2500] , ans , cur[2500] ; int mission[1205] , machine[1205] , S , T , id_c ; struct Path{ int pre , to , flow ; }p[2*2*1200 + 1200*1200*2 + 5] ; void In( int t1 , int t2 , int t3 ){ p[++tp] = ( Path ){ head[t1] , t2 , t3 } ; head[t1] = tp ; p[++tp] = ( Path ){ head[t2] , t1 , 0 } ; head[t2] = tp ; } int dis[2500] , que[2500] , fr , ba ; bool BFS(){ fr = 1 , ba = 0 ; memset( dis + 1 , -1 , id_c * sizeof( int ) ) ; dis[S] = 0 , que[++ba] = S ; while( fr <= ba ){ int u = que[fr++] ; for( int i = head[u] ; i ; i = p[i].pre ){ int v = p[i].to ; if( dis[v] != -1 || !p[i].flow ) continue ; dis[v] = dis[u] + 1 , que[++ba] = v ; } } return dis[T] != -1 ; } int dfs( int u , int flow ){ if( u == T ) return flow ; int rt = 0 ; for( int &i = cur[u] ; i ; i = p[i].pre ){ int v = p[i].to , nowf ; if( dis[v] != dis[u] + 1 || !p[i].flow ) continue ; if( ( nowf = dfs( v , min( flow , p[i].flow ) ) ) ){ rt += nowf ; flow -= nowf ; p[i].flow -= nowf ; p[i^1].flow += nowf ; if( !flow ) break ; } } if( flow ) dis[u] = -1 ; return rt ; } void solve(){ while( BFS() ){ memcpy( cur + 1 , head + 1 , id_c * sizeof( int ) ) ; ans -= dfs( S , 0x3f3f3f3f ) ; } printf( "%d" , ans ) ; } inline void read_( int &x ){ x = 0 ; char ch = getchar() ; while( ch < '0' || ch > '9' ) ch = getchar() ; while( ch >='0' && ch <='9' ) x = ( x << 1 ) + ( x << 3 ) + ch - '0' , ch = getchar() ; } int main(){ scanf( "%d%d" , &N , &M ) ; for( int i = 1 ; i <= N ; i ++ ) mission[i] = ++id_c ; for( int i = 1 ; i <= M ; i ++ ) machine[i] = ++id_c ; S = ++id_c , T = ++id_c ; for( int i = 1 , pro , cnt ; i <= N ; i ++ ){ scanf( "%d%d" , &pro , &cnt ) ; ans += pro ; In( S , mission[i] , pro ) ; for( int j = 1 , id , cost ; j <= cnt ; j ++ ){ read_( id ) , read_( cost ) ; In( mission[i] , machine[id] , cost ) ; } } for( int i = 1 , cost ; i <= M ; i ++ ){ scanf( "%d" , &cost ) ; In( machine[i] , T , cost ) ; } solve() ; }
相关文章推荐
- bzoj 1391 [Ceoi2008]order(最小割)
- BZOJ1391 [Ceoi2008]order 最小割
- 【bzoj1391】[Ceoi2008]order 网络流最小割
- 【bzoj1391】【Ceoi2008】【Order】【最小割】
- BZOJ 1391|CEOI 2008|Order|最小割
- bzoj 1391: [Ceoi2008]order(最小割)
- BZOJ 1391: [Ceoi2008]order [最小割]
- [BZOJ1391][Ceoi2008]order(最小割)
- 【BZOJ 1391】[Ceoi2008]order 最小割
- [CEOI2008] BZOJ 1391 order-最小割
- bzoj 1391 [Ceoi2008]order - 最小割
- BZOJ 1391 [Ceoi2008]order(最小割)
- 【CEOI2008】bzoj1391 order
- BZOJ1391: [Ceoi2008]order 最大权闭合子图
- BZOJ1391 [Ceoi2008]order
- BZOJ_1391_[Ceoi2008]order_最大权闭合子图
- bzoj1391 [Ceoi2008]order 网络流——最大权闭合子图
- 【bzoj1391】[Ceoi2008]order
- 【BZOJ】【1391】【CEOI2008】order
- BZOJ1391: [Ceoi2008]order