zoukankan      html  css  js  c++  java
  • poj2396 Budget 上下界可行流

    Budget:http://poj.org/problem?id=2396

    题意:

      给定一个棋盘,给定每一行每一列的和,还有每个点的性质。求一个合理的棋盘数值放置方式。

    思路:

      比较经典的网络流模型,把每一列看成一个点,每一行看成一个点,利用上下界可行流的思路建图就行了,注意这里由于是严格的小于和大于,所以可以利用 x+1, x-1。

    还有就是这道题的0 , 0 说的是对整张图的操作。

    #include <algorithm>
    #include  <iterator>
    #include  <iostream>
    #include   <cstring>
    #include   <cstdlib>
    #include   <iomanip>
    #include    <bitset>
    #include    <cctype>
    #include    <cstdio>
    #include    <string>
    #include    <vector>
    #include     <stack>
    #include     <cmath>
    #include     <queue>
    #include      <list>
    #include       <map>
    #include       <set>
    #include   <cassert>
    
    /*
    
    ⊂_ヽ
      \\ Λ_Λ  来了老弟
       \('ㅅ')
        > ⌒ヽ
       /   へ\
       /  / \\
       レ ノ   ヽ_つ
      / /
      / /|
     ( (ヽ
     | |、\
     | 丿 \ ⌒)
     | |  ) /
    'ノ )  Lノ
    
    */
    
    using namespace std;
    #define lson (l , mid , rt << 1)
    #define rson (mid + 1 , r , rt << 1 | 1)
    #define debug(x) cerr << #x << " = " << x << "
    ";
    #define pb push_back
    #define pq priority_queue
    
    typedef long long ll;
    typedef unsigned long long ull;
    //typedef __int128 bll;
    typedef pair<ll ,ll > pll;
    typedef pair<int ,int > pii;
    typedef pair<int,pii> p3;
    
    //priority_queue<int> q;//这是一个大根堆q
    //priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
    #define fi first
    #define se second
    //#define endl '
    '
    
    #define boost ios::sync_with_stdio(false);cin.tie(0)
    #define rep(a, b, c) for(int a = (b); a <= (c); ++ a)
    #define max3(a,b,c) max(max(a,b), c);
    #define min3(a,b,c) min(min(a,b), c);
    
    const ll oo = 1ll<<17;
    const ll mos = 0x7FFFFFFF;  //2147483647
    const ll nmos = 0x80000000;  //-2147483648
    const int inf = 0x3f3f3f3f;
    const ll inff = 0x3f3f3f3f3f3f3f3f; //18
    const int mod = 1e9+7;
    const double esp = 1e-8;
    const double PI=acos(-1.0);
    const double PHI=0.61803399;    //黄金分割点
    const double tPHI=0.38196601;
    
    template<typename T>
    inline T read(T&x){
        x=0;int f=0;char ch=getchar();
        while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x=f?-x:x;
    }
    
    inline void cmax(int &x,int y){if(x<y)x=y;}
    inline void cmax(ll &x,ll y){if(x<y)x=y;}
    inline void cmin(int &x,int y){if(x>y)x=y;}
    inline void cmin(ll &x,ll y){if(x>y)x=y;}
    
    /*-----------------------showtime----------------------*/
    
                const int maxn = 1e4+9;
                int n,m;
                struct E{
                    int v,val,id;
                    int nxt;
                }edge[maxn];
                int head[maxn],gtot;
                void addedge(int u,int v,int val, int id){
                    edge[gtot].v = v;
                    edge[gtot].val = val;
                    edge[gtot].nxt = head[u];
                    edge[gtot].id = -1;
                    head[u] = gtot++;
    
                    edge[gtot].v = u;
                    edge[gtot].val = 0;
                    edge[gtot].nxt = head[v];
                    edge[gtot].id = id;
                    head[v] = gtot++;
                }
    
                int dis[maxn],cur[maxn],all;
                bool bfs(int s,int t) {
                    memset(dis, inf, sizeof(dis));
    
                    for(int i=0; i<=all; i++) cur[i] = head[i];
                    queue<int>que;  que.push(s);
                    dis[s] = 0;
                    while(!que.empty()){
                        int u = que.front(); que.pop();
                        for(int i=head[u]; ~i; i=edge[i].nxt){
                            int v = edge[i].v,val = edge[i].val;
                            if(val > 0 && dis[v] > dis[u] + 1){
                                dis[v] = dis[u]+ 1;
                                que.push(v);
                            }
                        }
                    }
                    return dis[t] < inf;
                }
                int dfs(int u,int t,int maxflow){
                    if(u == t || maxflow == 0) return maxflow;
                    for(int i=cur[u]; ~i; i=edge[i].nxt){
                        cur[u] = i;
                        int v=edge[i].v,val = edge[i].val;
                        if(val > 0&&dis[v] == dis[u] + 1){
                            int f = dfs(v, t, min(maxflow, val));
                            if(f > 0) {
                                edge[i].val -= f;
                                edge[i ^ 1].val += f;
                                return f;
                            }
                        }
                    }
                    return 0;
                }
                int dinic(int s,int t){
                    int flow = 0;
                    while(bfs(s, t)){
                        while(int f = dfs(s, t, inf)) flow += f;
                    }
                    return flow;
                }
    
                int low[209][29],high[209][29],du[309];
                char op[5];
    int main(){
                int T;
                scanf("%d", &T);
                while(T--){
                    memset(head, -1, sizeof(head));
                    memset(low, 0, sizeof(low));
                    memset(high, inf, sizeof(high));
                    memset(du, 0, sizeof(du));
                    gtot = 0;
                    scanf("%d%d", &n, &m);
                    int s = 0, t = n+m+1, ss = n+m+2, tt = n+m+3;
                    all = tt;
                    int s1 = 0, s2 = 0;
                    for(int i=1; i<=n; i++) {
                        int x;  scanf("%d", &x);
                        addedge(s, i, 0, -1);
                        du[s] -= x;
                        du[i] += x;
                        s1 += x;
                    }
                    for(int i=1; i<=m; i++){
                        int x;  scanf("%d", &x);
                        addedge(n+i, t, 0, -1);
                        du[t] += x;
                        du[n+i] -= x;
                        s2 += x;
                    }
    
                    int c;  scanf("%d", &c);
                    int flag = 1;
                    while(c--){
                        int u,v,x;
                        scanf("%d %d %s %d", &u, &v, op, &x);
                        if(u == 0 && v == 0){
                            for(int i=1; i<=n; i++) {
                                    for(int j=1; j<=m; j++){
                                        if(op[0] == '>') low[i][j] = max(low[i][j],x+1);
                                        else if(op[0] == '<') high[i][j] = min(high[i][j], x-1);
                                        else if(op[0] == '=')
                                        {
                                            low[i][j] = max(low[i][j], x), high[i][j] = min(high[i][j], x);
                                            if(low[i][j] != x || high[i][j] != x) flag = 0;
                                        }
                                    }
                            }
                        }
                        else if(u == 0) {
                            for(int i=1; i<=n; i++) {
                                if(op[0] == '>') low[i][v] = max(low[i][v],x+1);
                                else if(op[0] == '<') high[i][v] = min(high[i][v], x-1);
                                else if(op[0] == '=')
                                {
                                    low[i][v] = max(low[i][v], x), high[i][v] = min(high[i][v], x);
                                    if(low[i][v] != x || high[i][v] != x) flag = 0;
                                }
                            }
                        }
                        else if(v == 0){
                            for(int i=1; i<=m; i++) {
                                if(op[0] == '>') low[u][i] = max(low[u][i],x+1);
                                else if(op[0] == '<') high[u][i] = min(high[u][i], x-1);
                                else {
                                    low[u][i] = max(low[u][i], x), high[u][i] = min(high[u][i], x);
                                    if(low[u][i] != x || high[u][i] != x) flag = 0;
                                }
                            }
                        }
                        else {
                             if(op[0] == '>') low[u][v] = max(low[u][v],x+1);
                             else if(op[0] == '<') high[u][v] = min(high[u][v], x-1);
                             else {
                                    low[u][v] = max(low[u][v], x), high[u][v] = min(high[u][v], x);
                                    if(low[u][v] != x || high[u][v] != x) flag = 0;
                             }
                        }
                    }
    
                    for(int i=1; i<=n; i++) {
                        for(int j=1; j<=m; j++){
                            du[i] -= low[i][j];
                            du[j+n] += low[i][j];
                            addedge(i, n + j, high[i][j] - low[i][j], 1);
                            if(high[i][j] < low[i][j]) flag = 0;
                        }
                    }
    
                    int sum = 0;
                    for(int i=s; i<=t; i++) {
                        if(du[i] > 0) addedge(ss, i, du[i], -1), sum += du[i];
                        if(du[i] < 0)addedge(i, tt, -du[i], -1);
                    }
                    if(s1 != s2 || !flag) {
                        puts("IMPOSSIBLE");
                        if(T) puts("");
                        continue;
                    }
                    int f = dinic(ss, tt);
    
                    if(f + s1==sum) {
                        for(int i=n+1;i<=n+m; i++){
                            for(int j=head[i]; ~j; j=edge[j].nxt){
                                int v = edge[j].v,val = edge[j].val;
                                low[v][i-n] += val;
                            }
                        }
                        for(int i=1; i<=n; i++){
                            for(int j=1; j<=m; j++){
                                if(j < m)printf("%d ", low[i][j]);
                                else printf("%d
    ", low[i][j]);
                            }
                        }
                    }
                    else puts("IMPOSSIBLE");
                    if(T) puts("");
                }
                return 0;
    }
    /*
    2
    2 3
    8 10
    5 6 7
    4
    0 2 > 2
    2 1 = 3
    2 3 > 2
    2 3 < 5
    2 2
    4 5
    6 7
    1
    1 1 > 10
    */
    View Code
  • 相关阅读:
    Working with macro signatures
    Reset and Clear Recent Items and Frequent Places in Windows 10
    git分支演示
    The current .NET SDK does not support targeting .NET Core 2.1. Either target .NET Core 2.0 or lower, or use a version of the .NET SDK that supports .NET Core 2.1.
    Build website project by roslyn through devenv.com
    Configure environment variables for different tools in jenkins
    NUnit Console Command Line
    Code Coverage and Unit Test in SonarQube
    头脑王者 物理化学生物
    头脑王者 常识,饮食
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/10544038.html
Copyright © 2011-2022 走看看