BZOJ 3698:XWW問題

説明

XWWは非常に影響力のある人物で、彼は信者の多くを持っています。これらの信者は、キリスト教徒がXWWのXWWに参加したいなると教示されています。しかし、これは、それはXWWの試験に合格する必要があり、容易ではありません。
XWWはあなたのうち、このような問題:XWWがあなたに正の実数A、XWW出会う抵抗のN×N行列を与えます。
N×N行列を満たすのいずれかが場合にのみプロパティをXWW言った:(1)A [N] [N] = 0;(2) 最後のN-1の各列の行列要素は、前列の数に等しく、 ;最後の要素(3)行列の各列は、前のN-1および列の数に等しいです。
今、あなたはA行列の最後には、まだXWWを満たすように、(丸めたり丸め上にあってもよい)A丸め演算の回数を与えたいです。なお更なる要素の要件と可能な限り大きくしXWW。

入力

整数N、N≤100の最初の行。
より小さい実数のN絶対値を含むまたは1000に等しく、小数点の場所まで次のn行。

出力

出力ライン、すなわち、A行列および丸め後の最大値の要素。解出力号ありません

サンプル入力

4

3.1 6.8 7.3 17.2

9.6 2.4 0.7 12.7

3.6 1.2 6.5 11.3

16.3 10.4 14.5 0

サンプル出力
129

ヒント

スケールデータと[合意]

Nサイズ10、20、... 100のためのデータの10セットは、それぞれ存在します。

[サンプル記述]

ミートXWWと最大マトリックス丸めのサンプルの後に:

3 7 8 18

10 3 0 13

4 1 7 12

17 11 15 0

解釈は、
アクティブシンクネットワークフローは、上限および下限を有する
数が彼の範囲[(INT)[i]の変化と言うことである、ダウン切り上げまたはすることができるように [I [j]は、(int)を] [J] +1];
Sからの各偶数行の側に、容量範囲[(INT)[I] [N]、(INT)[I] [N] +1];
Tの各列偶数側、容量範囲[(INT)N [] [i]は、(INT)[N] [i]を+1]は、
第i行j列も[(INT)[I] [ j]は、(int型)[ I] [J] +1] サイド
脇に下限を設定するためにも、この1.0 X.0のない側に、しかし(私は実際に直接進んでください...)

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
const int N = 1e4+100 , inf = 1e8;
inline int read()
{
    register int x = 0 , f = 0; register char c = getchar();
    while(c < '0' || c > '9') f |= c == '-' , c = getchar();
    while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
    return f ? -x : x;
}
int n , S , T , s , t , cnt = 1 , sum;
double a[120][120];
int head[N] , b[120][120] , du[N] , d[N];
struct edge{ int v , nex , c; } e[N<<4];
inline void add(int u , int v , int c) { e[++cnt].v = v; e[cnt].nex = head[u]; e[cnt].c = c; head[u] = cnt; e[++cnt].v = u; e[cnt].nex = head[v]; e[cnt].c = 0; head[v] = cnt; return ; }
queue<int> q;
bool bfs()
{
    for(int i = 1 ; i <= T+2 ; ++i) d[i] = 0; q.push(S); d[S] = 1;
    while(q.size())
    {
        int x = q.front(); q.pop();
        for(int i = head[x] , v; i ; i = e[i].nex)
        {
            v = e[i].v; if(d[v] || e[i].c == 0) continue;
            d[v] = d[x] + 1; q.push(v);
        }
    }
    return d[T] != 0;
}

int dfs(int x , int flow)
{
    if(x == T || flow == 0) return flow;
    int res = 0 , k;
    for(int i = head[x] , v; i ; i = e[i].nex)
    {
        v = e[i].v;
        if(d[v] == d[x] + 1 && e[i].c)
        {
            k = dfs(v , min(e[i].c , flow));
            if(k) { e[i].c -= k; e[i^1].c += k; res += k; flow -= k; if(flow == 0) return res; }
            else d[v] = 0;
        }
    }
    return res;
}

int Dinic()
{
    int ans = 0;
    while(bfs()) ans += dfs(S , inf);
    return ans;
}

void solve()
{
    s = n*2+1; t = s+1; S = t+1; T = S+1;
    for(int i = 1 ; i <= n ; ++i) for(int j = 1 ; j <= n ; ++j) b[i][j] = (int)a[i][j];
    for(int i = 1 ; i < n ; ++i)
    {
        if(a[i][n] != b[i][n]) add(s , i , 1);
        du[s] -= b[i][n]; du[i] += b[i][n]; // 相等 
        if(a[n][i] != b[n][i]) add(i+n , t , 1);
        du[i+n] -= b[n][i]; du[t] += b[n][i];
    }
    for(int i = 1 ; i < n ; ++i) for(int j = 1 ; j < n ; ++j) 
    {
        if(a[i][j] != b[i][j]) add(i , j+n , 1);
        du[i] -= b[i][j]; du[j+n] += b[i][j];
    }
    for(int i = 1 ; i <= T ; ++i) if(du[i] > 0) add(S , i , du[i]) , sum += du[i]; else if(du[i] < 0) add(i , T , -du[i]);
    add(t , s , inf);
    int ans = Dinic();
    if(ans != sum) puts("No");
    else
    {
        S = s; T = t;
        cout << Dinic() * 3 << '\n';
    }
    return ;
}

int main()
{
    n = read();
    for(int i = 1 ; i <= n ; ++i) for(int j = 1 ; j <= n ; ++j) scanf("%lf" , &a[i][j]);
    solve();
    return 0;
}

おすすめ

転載: www.cnblogs.com/R-Q-R-Q/p/12332712.html