zoukankan      html  css  js  c++  java
  • ACM/ICPC 之 有流量上下界的网络流-Dinic(可做模板)(POJ2396)

    //有流量上下界的网络流
    //Time:47Ms     Memory:1788K
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    
    #define MAXC 25
    #define MAXN 250
    #define MAXE 100000
    #define INF 0x3f3f3f3f
    
    struct Edge{
        int u,v,f,next;
        Edge(){}
        Edge(int uu, int vv, int ff, int nn):u(uu), v(vv), f(ff), next(nn){}
    }e[MAXE];
    
    int n, m;
    int S,T,s,t;
    int sn[MAXN], sm[MAXC]; //行和,列和
    int up[MAXN][MAXC], down[MAXN][MAXC];      //上界与下界
    int in[MAXN], out[MAXN];    //出入度
    int h[MAXN], le;
    int d[MAXN];
    int ans[MAXN][MAXC];
    
    void add(int u,int v,int f)
    {
        e[le] = Edge(u, v, f, h[u]);    h[u] = le++;
        e[le] = Edge(v, u, 0, h[v]);    h[v] = le++;
    }
    
    bool Init()
    {
        int TT;
        bool result = true;
        scanf("%d", &TT);
        while(TT--){
            int x, y, v;
            int x1,x2,y1,y2;
            char op[2];
            scanf("%d%d%s%d", &x, &y, op, &v);
            if(!result) continue;
            x1 = x2 = x;    y1 = y2 = y;
            if(x == 0){ x1 = 1; x2 = n;}
            if(y == 0){ y1 = 1; y2 = m;}
            for(int i = x1; i <= x2; i++)
            {
                for(int j = y1; j <= y2; j++)
                {
                    if(op[0] == '='){
                        if(v > up[i][j] || v < down[i][j]) result = false;
                        up[i][j] = down[i][j] = v;
                    }
                    else if(op[0] == '>')
                        down[i][j] = max(down[i][j], v+1);
                    else up[i][j] = min(up[i][j], v-1);
                    if(up[i][j] < down[i][j]) result = false;
                }
            }
        }
        return result;
    }
    
    void Build()    //建图
    {
        memset(h, -1, sizeof(h));
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        le = 0;
        s = 0;  t = n+m+1;  //原图源汇点
        S = t+1;  T = t+2;  //超级源汇点
        for(int i =1; i <= n; i++)  //建立初始各边
        {
            for(int j = 1; j <= m; j++)
            {
                int x = i, y = j + n;
                add(x, y, up[i][j] - down[i][j]);
                in[y] += down[i][j];    out[x] += down[i][j];
            }
        }
        for(int i = 1; i <= n; i++)   //从s流出的流量
        {
            in[i] += sn[i];   out[s] += sn[i];
        }
        for(int i = 1; i <= m; i++) //到t的流量
        {
            in[t] += sm[i]; out[i+n] += sm[i];
        }
        for(int i = 0; i <= n+m+1; i++) //新建补边
        {
            int x,y,w;
            if(in[i] > out[i])  {
                out[S] += in[i] - out[i];
                add(S,i,in[i] - out[i]);
            }
            else if(in[i] < out[i]) add(i, T, out[i] - in[i]);
        }
        add(t, s, INF);
    }
    
    bool BFS()
    {
        memset(d, -1, sizeof(d));
        queue<int> q;
        q.push(S);  d[S] = 0;
        while(!q.empty()){
            int cur = q.front();
            q.pop();
            for(int i = h[cur]; i != -1; i = e[i].next)
            {
                int v = e[i].v;
                if(d[v] == -1 && e[i].f)
                {
                    d[v] = d[cur] + 1;
                    if(v == T) return true;
                    q.push(v);
                }
            }
        }
        return false;
    }
    
    int DFS(int x, int sum)
    {
        if (x == T || sum == 0) return sum;
    	int src = sum;
    	for (int i = h[x]; i != -1; i = e[i].next)
    	{
    	    int v = e[i].v;
    		if (d[v] == d[x] + 1 && e[i].f)
    		{
    			int tmp = DFS(v, min(sum, e[i].f));
    			e[i].f -= tmp;
    			e[i^1].f += tmp;
    			sum -= tmp;
    		}
    	}
    	return src - sum;
    }
    
    int Dinic()
    {
        int maxflow = 0;
        while(BFS()){
            maxflow += DFS(S, INF);
        }
        return maxflow;
    }
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        int TT;
        scanf("%d",&TT);
        while(TT--){
            memset(e, 0, sizeof(e));
            memset(up, INF, sizeof(up));
            memset(down, 0 ,sizeof(down));
            scanf("%d%d", &n,&m);
            for(int i = 1; i <= n; i++)
                scanf("%d", &sn[i]);
            for(int i = 1; i <= m; i++)
                scanf("%d", &sm[i]);
            if(!Init()){   //预处理得到矛盾
                printf("IMPOSSIBLE
    
    ");
                continue;
            }
            Build();    //构图
            if(Dinic() != out[S])   printf("IMPOSSIBLE
    
    ");
            else{
                for(int i = 1; i <= n; i++)
                    for(int j = h[i]; j != -1; j = e[j].next)
                        ans[i][e[j].v-n] = e[j^1].f + down[i][e[j].v-n];
                for(int i = 1; i <= n; i++)
                {
                    for(int j = 1; j < m; j++)
                        printf("%d ", ans[i][j]);
                    printf("%d
    ", ans[i][m]);
                }
                printf("
    ");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Python+SparkStreaming+kafka+写入本地文件案例(可执行)
    Python安装pycurl失败,及解决办法
    Linux screen用法简介
    [算法]数组中求出下标不连续的任意个数,使得和最大
    消息队列小结
    [算法]计算全排列组合数
    [数据结构]A*寻路算法
    [数据结构]最大流之Ford-Fulkerson算法
    [数据结构]最小生成树算法Prim和Kruskal算法
    [数据结构]迪杰斯特拉(Dijkstra)算法
  • 原文地址:https://www.cnblogs.com/Inkblots/p/5740650.html
Copyright © 2011-2022 走看看