# uva 10983 Buy one, get the rest free 二分判定层次图

1. e天有飞机从a城市飞到b城市，能够承载x人，则添加单向边 ( e, a ) -> ( e+1, b ) 容量为x

2. 每一天的a城市到第二天的a城市连边，容量为正无穷大

3. 每一天的N城市到汇点T连边，容量为正无穷大

4. 源点V与第0天的所有顶点连边，容量为当前城市0天初始人数

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
using namespace std;
const int M = 1010;
const int inf = 0x3f3f3f3f;
int n, d, m, tot;
struct Fight{
int u, v;
int c, p, e;
void input(){
scanf("%d%d%d%d%d",&u,&v,&c,&p,&e);
}
}fight[M];
int people[35];
int S, T, N;
struct Edge{
int v, f, nxt;
}edge[250011];

edge[idx].v = v, edge[idx].f = f;
edge[idx].v = u, edge[idx].f = 0;
}
void CreateGraph(int Max){
//init
idx = 0;
S = 0, T = (d+1)*n+1, N = (d+1)*n+2;
int u, v, c, p, e;
for(int i = 0; i < m; i++){
u = fight[i].u, v = fight[i].v, c = fight[i].c, p = fight[i].p, e = fight[i].e;
if( p <= Max ) AddEdge( e*n+u, (e+1)*n+v, c );
}
for(int i = 1; i <= n; i++ )
for(int d1 = 0; d1 < d; d1++ ){
for(int i = 1; i <= n; i++ )
}
for(int d1 = 0; d1 <= d; d1++ )
}
int h[400], vh[400];

int dfs(int u, int flow ){
if( u == T ) return flow;
int t = h[u]+1, sum = flow;
for(int i = head[u]; ~i; i = edge[i].nxt ){
int v = edge[i].v;
if( edge[i].f && (h[v]+1==h[u]) ){
int tmp = dfs( v, min(sum,edge[i].f) );
edge[i].f -= tmp, edge[i^1].f += tmp; sum -= tmp;
if( sum == 0 || h[S] == N ) return flow-sum;
}
}
for(int i = head[u]; ~i; i = edge[i].nxt )
if( edge[i].f ) t = min( t, h[ edge[i].v ] );
if( --vh[ h[u] ] == 0 ) h[S] = N;
else ++vh[ h[u] = t+1 ];
return flow - sum;
}
int sap(){
int maxflow = 0;
memset( h, 0, sizeof(h));
memset( vh, 0, sizeof(vh));
vh[0] = N;
while( h[S] < N ) maxflow += dfs( S, inf );
return maxflow;
}
int solve(){
int ans = -1;
int l = 0, r = 100000;
while( l <= r ){
int mid = (l+r)>>1;
CreateGraph( mid );
int tmp = sap(); //printf("tmp = %d\n", tmp);
if( tmp >= tot ) ans = mid, r = mid-1;
else l = mid+1;
}
return ans;
}
int main(){
int _;
scanf("%d",&_);
for(int Case = 1; Case <= _; Case++){
scanf("%d%d%d",&n,&d,&m);
int u, v, c, p, e;
for(int i = 0; i < m; i++)
fight[i].input();
tot = 0;
for(int i = 1; i <= n; i++){
scanf("%d", &people[i] );
tot += people[i];
}
int ans = solve();
printf("Case #%d: ", Case );
if( ans == -1 ) puts("Impossible");
else printf("%d\n", ans );
}
return 0;
}
View Code

posted @ 2013-07-06 21:04  yefeng1627  阅读(458)  评论(0编辑  收藏  举报