这道题,水很深,线性代数当初没学好,一看见矩阵就颤抖,比赛的时候都没敢看这题,后来发布解题报告后才知道这是最小割。

建图,求maxflow,然后res-maxflow(n+1)即为所求。

用dinic居然超时了,happy457曾经告诉我dinic是永远不会出现超时现象的,它居然超时了。冷静思考一下dinic-O(V^2*E)与hlpp-O(V^2*sqrt(E))在该题上确实有差别,因为E=V*(V-1)/2,瞬间dinic复杂度变为O(V^4),而hlpp为O(V^3).我又一直没去理解hlpp,所以到网上搜了份模板,套上建图,果然1Y了。没想到的是排名倒数第一。囧。。

附AC代码:

View Code
#include <stdio.h>
#include <queue>
#include <string.h>
using namespace std;
#define V 1005
int res;
queue<int> que;
int ori[V][V];
int rm[V][V];
int high[V];
int e[V];
int m,n;
int b[V][V];
int c[V];
void init(){
          memset(high,0,sizeof(high));
          memset(e,0,sizeof(e));
          while(!que.empty()){
                  que.pop();
          }
          high[0]=n+1;
          int i;
          for(i=0;i<=n+1;++i){
                  if(ori[0][i]>0){
                          e[0]-=ori[0][i];
                          e[i]+=ori[0][i];
                          rm[0][i]=ori[0][i];
                          rm[i][0]=-rm[0][i];
                          que.push(i);
                  }
          }
}
int fpath(int num){
          int i;
          int small=0x7fffffff;
          int spos;
          for(i=0;i<=n+1;++i){
                  if(ori[num][i]-rm[num][i]>0){
                          if(high[num]==high[i]+1){
                                  return i;
                          }
                          if(high[i]< small){
                                  small=high[i];
                                  spos=i;
                          }
                  }
          }
          high[num]=small+1;
          return spos;
}
void push(int s,int d){
          int max=ori[s][d]-rm[s][d];
          if(e[s]< max){
                  max=e[s];
          }
          e[s]-=max;
          e[d]+=max;
          rm[s][d]+=max;
          rm[d][s]=-rm[s][d];
}
void deal(){
          int now;
          int psta;
          while(!que.empty()){
                  now=que.front();
                  que.pop();
                  if(now==n+1){
                          continue;
                  }
                  while(e[now]>0){
                          psta=fpath(now);
                          push(now,psta);
                          que.push(psta);
                  }
          }
}
void build(){
    res=0;
    for(int i=1;i<=n;i++){
        ori[0][i]+=c[i];
        //addedge(0,i,c[i]);
        int sum=0;
        for(int j=1;j<=n;j++){
            sum+=b[i][j];
            if(i==j) continue;
            ori[j][i]+=b[i][j];
            //addedge(j,i,b[i][j]);
        }
        ori[i][n+1]+=sum;
        //addedge(i,n+1,sum);
        res+=sum;
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    int ncas;
    scanf("%d",&ncas);
    while(ncas--){
        memset(ori,0,sizeof(ori));
        memset(rm,0,sizeof(rm));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&b[i][j]);
        for(int i=1;i<=n;i++)
            scanf("%d",&c[i]);
        build();
        init();
        deal();
        printf("%d\n",res-e[n+1]);
    }
    return 0;
}