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

二分枚举租用飞机的最大花费,然后用小于等于最大花费的边构建层次图(依据时间)

构图思路:   利用二元组(x,y)表示 x天y城市

  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];
int head[350], idx;

void AddEdge(int u,int v,int f){
    edge[idx].v = v, edge[idx].f = f;
    edge[idx].nxt = head[u], head[u] = idx++;
    edge[idx].v = u, edge[idx].f = 0;
    edge[idx].nxt = head[v], head[v] = idx++;
}
void CreateGraph(int Max){
    //init
    idx = 0;
    memset( head, -1, sizeof(head));
    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++ )
        AddEdge( S, i, people[i] );
    for(int d1 = 0; d1 < d; d1++ ){
        for(int i = 1; i <= n; i++ )
            AddEdge( d1*n+i, (d1+1)*n+i, inf );
    }
    for(int d1 = 0; d1 <= d; d1++ )
        AddEdge( d1*n+n, T, inf );
}
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  阅读(461)  评论(0编辑  收藏  举报

Launch CodeCogs Equation Editor