某岛

… : "…アッカリ~ン . .. . " .. .
August 18, 2010

ZOJ 2587. Unique Attack

Brief description :

判断流网络割是否唯一。

Analyse :

最大流完事以后,从源点和汇点处分别染色。

/*
    Author: xiaodao    
    Prob: ZOJ 2587. Unique Attack        
    Date: GMT +8 Aug.19th 02:36
    Status: Accepted        
    Tags: Network-Flow
*/

#include 
#include 
#include 
using namespace std;
const int INF = 0x7fffffff, BLACK = 0, RED = 1, BLUE = 2;
const int N = 1001;
int C[N][N], D[N];
int n, m, s, t;

void bfs(){
    int Q[N], head, tail;
    memset(D, -1, sizeof(D));
    head = 0; tail = 1; Q[0] = s; D[s] = 0;

    int u, v;
    while (headn) D[u] = -1, top--;
            else {
                cur[u] = v + 1;
                stack[++top] = v;
            }
        }
        bfs();
    }
}



void init(){
    memset(C, 0, sizeof(C));
    int x, y, c;
    for (int i=1;i<=m;i++){
        scanf("%d%d%d", &x, &y, &c);
        C[x][y] += c; C[y][x] += c;
    }
}

bool unique(){
    int queue[N]; int color[N];
    int head, tail, u, v;
    memset(color, BLACK, sizeof(color));
    head = 0; tail = 1; queue[0] = s; color[s] = RED;


    while (head0){
                queue[tail++] = v;
                color[v] = RED;
            }
        }
        head++;
    }

    head = 0; tail = 1; queue[0] = t; color[t] = BLUE;
    while (head=1;u--){
            if (color[u]!=BLUE && C[u][v]>0){
                if (color[u] == RED) return false;
                queue[tail++] = u;
                color[u] = BLUE;
            }
        }
        head++;
    }

    for (int i=1;i<=n;i++)
        if (color[i] == BLACK) return false;
    return true;
}



int main(){
    while (scanf("%d%d%d%d", &n, &m, &s, &t) != EOF && n > 0){
        init(); Dinitz();
        puts(unique() ? "UNIQUE" : "AMBIGUOUS");
    }
}

Further discuss :

好了我来说点正事。。。我这几天爆写了十几个(几个啦)各种网络流的题。
。。。比如说像是这个。。昨晚就写完了。。然后一直WA一直WA。。心想。。难不成我的 Relabel 有BUG?#。 (于是几个深夜又学习了 Dinitz … Sap … 目前按照计划只差一个 HLPP 了。。)

但是我继续爆WA..

于是我发现我WA的几个网络流都有一些共同点。。。
(快说啊。。。#)

事实上。。因为我人工将源点和汇点固定成 1 && n 会有许多说不清的好处。。。(例如。。我总是可以优化。。#。#)

...
    if (s!=1){
        for (int i=1;i<=n;i++){
            if (i==1||i==s) continue;
            swap(C[1][i], C[s][i]);
            swap(C[i][1], C[i][s]);
        }
        swap(C[1][s], C[s][1]);
    }

    if (t!=n){
        for (int i=1;i<=n;i++){
            if (i==n||i==t) continue;
            swap(C[n][i], C[t][i]);
            swap(C[i][n], C[i][t]);
        }
        swap(C[n][t], C[t][n]);
    }
    s = 1; t = n;
                              ....

实际上。。我之前的方案更暴力。。就是一个循环里面嵌两个交换。。
(但是我已经发现那样是错误的了。。。但是我不能发现。。这个错在哪。)