JZOJ4718. 准备食物2
来源:互联网 发布:仙剑4 mac 怎么全屏 编辑:程序博客网 时间:2024/04/29 00:42
题目大意
给定
现在要按编号顺序给
求每个宠物分配到一份食物且满足所有约束的情况下最多能获得多少喜悦值。
Data Constraint
题解
比较明显是费用流。
假如没有约束条件,连边就比较简单了。具体来说:
S 向每个宠物连(1,0) - 每个宠物向每种食物连
(1,vi,j) - 每种食物向
T 连(ai,0)
现在的问题是如何处理约束条件。我们把
SRC
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std ;#define N 200 + 10#define M 100000 + 10struct Note { int h , s ; Note ( int H = 0 , int S = 0 ) { h = H , s = S ; }} ;Note Sta[N][N] ;int top[N] ;bool vis[2*M] ;int Node[2*M] , Next[2*M] , C[2*M] , Cost[2*M] , Head[2*M] , tot = 1 ;int D[10*M] , Dist[2*M] , Pre[2*M] ;int use[N] ;int v[N][N] ;int s[N] , num[N] , a[N] ;int Case , n , m , Suma ;int S , T , ans , MaxFlow ;void link( int u , int v , int w , int fee ) { Node[++tot] = v , Next[tot] = Head[u] , C[tot] = w , Cost[tot] = fee , Head[u] = tot ; Node[++tot] = u , Next[tot] = Head[v] , C[tot] = 0 , Cost[tot] = -fee , Head[v] = tot ;}void MakeGraph() { tot = 1 ; S = 0 , T = n * (m + 1) + 1 ; memset( Head , 0 , sizeof(Head) ) ; for (int i = 1 ; i <= n ; i ++ ) { link( S , i , 1 , 0 ) ; } for (int i = 1 ; i <= m ; i ++ ) { Sta[i][++top[i]] = Note( n + 1 , 0x7FFFFFFF ) ; int last = 1 ; for (int j = 1 ; j <= top[i] ; j ++ ) { if ( j ) link( n + (j - 2) * m + i , n + (j - 1) * m + i , Sta[i][j-1].s , 0 ) ; for (int k = last ; k < Sta[i][j].h ; k ++ ) { link( k , n + (j - 1) * m + i , 1 , -v[k][i] ) ; } last = Sta[i][j].h ; } link( n + (top[i] - 1) * m + i , T , a[i] , 0 ) ; }}bool SPFA() { memset( vis , 0 , sizeof(vis) ) ; memset( Dist , 63 , sizeof(Dist) ) ; int i = 0 , j = 1 ; D[1] = S ; vis[S] = 1 ; Dist[S] = 0 ; while ( i < j ) { i ++ ; int now = D[i] ; for (int p = Head[now] ; p ; p = Next[p] ) { if ( !C[p] ) continue ; if ( Dist[now] + Cost[p] < Dist[Node[p]] ) { Dist[Node[p]] = Dist[now] + Cost[p] ; Pre[Node[p]] = p ; if ( !vis[Node[p]] ) { vis[Node[p]] = 1 ; D[++j] = Node[p] ; if ( Dist[D[i+1]] > Dist[D[j]] ) swap( D[i+1] , D[j] ) ; } } } vis[now] = 0 ; } return Dist[T] < Dist[T+1] ;}void Flow() { ans = MaxFlow = 0 ; while ( SPFA() ) { int Minv = 0x7FFFFFFF ; for (int x = T ; x != S ; x = Node[Pre[x]^1] ) Minv = min( Minv , C[Pre[x]] ) ; ans -= Minv * Dist[T] ; MaxFlow += Minv ; for (int x = T ; x != S ; x = Node[Pre[x]^1]) { C[Pre[x]] -= Minv ; C[Pre[x]^1] += Minv ; } }}int main() { scanf( "%d" , &Case ) ; while ( Case -- ) { ans = -1 ; Suma = 0 ; scanf( "%d%d" , &n , &m ) ; for (int i = 1 ; i <= n ; i ++ ) { for (int j = 1 ; j <= m ; j ++ ) { scanf( "%d" , &v[i][j] ) ; } } memset( top , 0 , sizeof(top) ) ; for (int i = 1 ; i <= n ; i ++ ) { scanf( "%d%d" , &s[i] , &num[i] ) ; if ( num[i] < 0 ) continue ; while ( top[num[i]] && Sta[num[i]][top[num[i]]].s >= s[i] ) top[num[i]] -- ; Sta[num[i]][++top[num[i]]] = Note( i , s[i] ) ; } for (int i = 1 ; i <= m ; i ++ ) scanf( "%d" , &a[i] ) , Suma += a[i] ; if ( Suma < n ) { printf( "Warning!\n" ) ; continue ; } MakeGraph() ; Flow() ; if ( MaxFlow < n ) printf( "Warning!\n" ) ; else printf( "%d\n" , ans ) ; } return 0 ;}
以上.
2 0
- JZOJ4718. 准备食物2
- 【JZOJ4718】准备食物2 题解
- 准备食物
- 准备食物
- 【GDOI2017模拟8.20】准备食物2
- 【JZOJ 4598】准备食物
- 【JZOJ 4598】 准备食物
- 【JZOJ4598】准备食物
- jzoj 4718. 【GDOI2017模拟7.20】准备食物2 费用流
- 【jzoj4598】【准备食物】【字典树】
- 准备食物(trie) 题解+代码
- [jzoj4598]【NOIP2016模拟7.9】准备食物
- 食物
- 食物
- 康康准备了 M 斤的食物, 准备跟舍长交换哲学之宝 ♂
- 最润肤的10种天然食物 为夏季做准备哟!
- 第2章 准备——2.1. 准备的准备
- 《白话C++》第2章 准备 2.1 准备的准备
- VPN 身份认证协议
- 108.UIView关于布局和约束的方法(AutoLayout)
- jquery easyui datagrid 分页 详解
- TYZ群赛 8/21解题报告
- Javascript——尺寸和定位(操作指南)
- JZOJ4718. 准备食物2
- Codeforces Round #368 (Div. 2) C. Pythagorean Triples(数学构造)
- HTML5 手势检测原理和实现
- alibaba fastJson框架
- android studio svn版本控制
- 华为OJ 走迷宫 Java BFS
- linux文件交集差集
- X86汇编语言从实模式到保护模式(一)
- NC工具的使用说明教程