1. 程式人生 > >平面圖的最小割轉最短路(點非常多)

平面圖的最小割轉最短路(點非常多)

/**************************************************************
    User: error408
    Language: C/C++
    School: SSDUT
    Saying: Do one thing at a time,and do well.
****************************************************************/
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
using namespace std;

#pragma comment(linker,"/STACK:102400000,102400000") /// kuo zhan
#define clr(s,x) memset((s),(x),sizeof(s))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lowbit(x) (x&(-x))
#define PB push_back
#define For(i,a,b) for(int i=a;i<b;i++)
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define RL(N) scanf("%I64d",&N)
#define RLL(L,R) (RL(L),RL(R))

typedef long long               LL;
typedef unsigned int            uint;
typedef unsigned long long      ULL;
typedef vector<int>             vint;
typedef vector<string>          vstring;

void RI (int& x){
    x = 0;
    char c = getchar ();
    while (c == ' '||c == '\n')    c = getchar ();
    bool flag = 1;
    if (c == '-'){
        flag = 0;
        c = getchar ();
    }
    while (c >= '0' && c <= '9'){
        x = x * 10 + c - '0';
        c = getchar ();
    }
    if (!flag)    x = -x;
}
void RII (int& x, int& y){RI (x), RI (y);}
void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);}

/************************************END DEFINE*********************************************/

const int maxn = 1e6 + 1000;
const int maxm = 4e6 + 1000;
const int inf  = 0x7fffffff;

struct Side{
    int to,next,w;
}side[maxm];
int n,m,T,s,e,cnt;
int top,node[maxn];

inline void add_side(int u,int v,int c){
    side[top]=(Side){v,node[u],c};
    node[u]=top++;
    side[top]=(Side){u,node[v],c};
    node[v]=top++;
}

bool inque[maxn];
int dis[maxn];
int q[maxn];
int spfa(){
    int head,tail;
    head = tail = 0;
    for(int i=0;i<cnt;i++){
        dis[i]=inf;
        inque[i]=false;
    }
    dis[s]=0;
    q[tail++]=s;
    while(head!=tail){
        int u=q[head++];
        head%=maxn;
        inque[u]=false;
        for(int i=node[u];i!=-1;i=side[i].next){
            int v=side[i].to;
            if(dis[u]+side[i].w<dis[v]){
                dis[v]=dis[u]+side[i].w;
                if(!inque[v]){
                    inque[v]=true;
                    q[tail++]=v;
                    tail%=maxn;
                }
            }
        }
    }
    return dis[e];
}

void init(){
    top = 0;
    clr(node,-1);
}
int main()
{
    scanf("%d",&T);
    while(T--){
        init();
        scanf("%d%d",&n,&m);
        s = (n-1)*(m-1);
        e = (n-1)*(m-1)+1;
        cnt = (n-1)*(m-1)+2;
        int w;
        for(int i=0;i<n-1;i++){
            scanf("%d",&w);
            add_side(e,i*(m-1),w);
            for(int j=1;j<m-1;j++){
                scanf("%d",&w);
                add_side(i*(m-1)+j,i*(m-1)+j-1,w);
            }
            scanf("%d",&w);
            add_side(s,i*(m-1)+m-2,w);
        }
        for(int j=0;j<m-1;j++){
            scanf("%d",&w);
            add_side(j,s,w);
        }
        for(int i=1;i<n-1;i++)
        for(int j=0;j<m-1;j++){
            scanf("%d",&w);
            add_side(i*(m-1)+j,(i-1)*(m-1)+j,w);
        }
        for(int j=0;j<m-1;j++){
            scanf("%d",&w);
            add_side(e,(n-2)*(m-1)+j,w);
        }
        printf("%d\n",spfa());
    }
    return 0;
}