[JZOJ1900] [2010] Matrix Team topic

topic

Subject to the effect

Title about simplification, becomes:
constructing a \ (01 \) series \ (A \) , so \ (D = \ sum A_iA_jB_ { i, j} - \ sum A_iC_i \) maximum.
I asked the biggest \ (D \) is.


Correct

In fact, this is a binary relationship between a network flow ......
if \ (A_i \) to \ (1 \) , then there \ (- C_i \) contribution.
If \ (A_i \) and \ (A_j \) are both \ (1 \) , then there will be \ (B_ {i, j} \) contribution.
Clearly then, \ (70 \) method points arise: each point toward a sink capacity is connected \ (C_i \) side, for each \ (B_ {I, J} \) , Jian a new point, which is connected from the source towards a capacity \ (B_ {i, j} \) side, toward which \ (I \) and \ (J \) connected capacity side is infinite. Then cut to a minimum.
This algorithm is that these new bottleneck point too much, can not create a new point?
There are actually a very subtle way: for each pair of \ (I \) and \ (J \) , from the origin to the \ (I \) is connected a capacity \ (B_ {i, j} \) side, Similarly to \ (j \)Even a capacity \ (B_ {j, i} \) side. \ (I \) to \ (J \) is connected a capacity \ (B_ {i, j} \) side, \ (J \) to \ (I \) is connected a capacity \ (B_ {j, i } \) side.
So this what use is it? When \ (C_i \) when that edge is reserved, the source \ (I \) connected piece \ (B_ {i, j} \) side is cut off, and the source is connected to the \ (J \) or \ (J \) is connected to the \ (I \) will be cut off of that edge.

Another embodiment with this construction of FIG analogous, but the right side into the \ (\ frac {B_ {i , j} + B_ {j, i}} {2} \) nothing. As long Reserved \ (C_i \) or \ (C_J \) , the edges are cut off \ (B_ {I, J} + {B_ J, I} \) .
For the source to \ (I \) and \ (J \) connected edges, apparently can be combined. FIG point and so the number of edges is greatly reduced.


Code

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#define N 610
inline int input(){
    char ch=getchar();
    while (ch<'0' || '9'<ch)
        ch=getchar();
    int x=0;
    do{
        x=x*10+ch-'0';
        ch=getchar();
    }
    while ('0'<=ch && ch<='9');
    return x;
}   
int n;
int b[N][N],c[N];
struct EDGE{
    int to,c;
    EDGE *las;  
} e[2000000];
int ne;
EDGE *last[N];
inline void link(int u,int v,int c){
    e[ne]={v,c,last[u]};
    last[u]=e+ne++;
}
int S,T;
#define rev(ei) (e+(((ei)-e)^1))
int dis[N],gap[N],BZ;
EDGE *cur[N];
int dfs(int x,int s){
    if (x==T)
        return s;
    int have=0;
    for (EDGE *ei=cur[x];ei;ei=ei->las){
        cur[x]=ei;
        if (ei->c && dis[x]==dis[ei->to]+1){
            int t=dfs(ei->to,min(s-have,ei->c));
            ei->c-=t,rev(ei)->c+=t,have+=t;
            if (have==s)
                return s;
        }
    }
    cur[x]=last[x];
    if (!--gap[dis[x]])
        BZ=0;
    dis[x]++;
    gap[dis[x]]++;
    return have;
}
inline int flow(){
    gap[0]=n+2;
    int res=0;
    BZ=1;
    while (BZ)
        res+=dfs(S,INT_MAX);
    return res;
}
int main(){
    n=input();
    for (int i=1;i<=n;++i)
        for (int j=1;j<=n;++j)
            b[i][j]=input();
    for (int i=1;i<=n;++i)
        c[i]=input();
    S=n+1,T=n+2;
    int all=0;
    for (int i=1;i<=n;++i){
        int sum=0;
        for (int j=1;j<=n;++j)
            sum+=b[j][i];
        all+=sum;
        link(S,i,sum),link(i,S,0);
        for (int j=1;j<i;++j)
            link(i,j,b[j][i]),link(j,i,b[i][j]);
        link(i,T,c[i]),link(T,i,0);
    }
    printf("%d\n",all-flow());
    return 0;
}

to sum up

See the type of binary relations problem, we must first think of network flow ah ......

Guess you like

Origin www.cnblogs.com/jz-597/p/11423015.html