• 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
    ", 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
    ", ans );
        }
        return 0;
    }
    View Code
  • 相关阅读:
    在Linux下运行YY,WINE方式,主要注册表修改点及字体文件列表
    安卓so下,cmake编译系统,如何仅导出指定符号
    AutoHotKey脚本模板:初始化、配置、退出
    资源ID管理插件:VS6/VS.NET
    ListView控件,表格模式下,如何调整行高
    通过wscript运行的JS脚本,如何引入另一个JS文件
    64位编译器下,将指针转换成UINT32,不需要修改编译选项的编码方式
    视频帧双缓冲区的两个版本
    opencv、numpy中矩阵转置,矩阵内的固定位置相应的坐标变换
    CMake下,某些选项的后调整
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/3175522.html
Copyright © 2020-2023  润新知