hdu 3870 Catch the Theves 最小割-》求最短路

题意:

给你一个n*n的矩阵,然后(0,0)为源点,(n - 1,n  - 1)为汇点。点(i,j)可以到达(i + 1,j) (i,j + 1) 花费为a[i][j]。求从(0,0)到(n - 1,n - 1)的最小割。

思路:

如果按照正常建图,Dinic求最大流会超时,这里要充分利用平面图的性质。然后将其转化为对偶图,然后将求最大流最小割转化为求该图的对偶图最短路问题。

详细请参考:http://wenku.baidu.com/view/5a7df375a417866fb84a8e54.html

#include <iostream>

#include <cstdio>

#include <cmath>

#include <vector>

#include <cstring>

#include <algorithm>

#include <string>

#include <set>

#include <functional>

#include <numeric>

#include <sstream>

#include <stack>

#include <map>

#include <queue>



#define CL(arr, val) memset(arr, val, sizeof(arr))



#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define L(x)    (x) << 1

#define R(x)    (x) << 1 | 1

#define MID(l, r)   (l + r) >> 1

#define Min(x, y)   (x) < (y) ? (x) : (y)

#define Max(x, y)   (x) < (y) ? (y) : (x)

#define E(x)        (1 << (x))

#define iabs(x)     (x) < 0 ? -(x) : (x)

#define OUT(x)  printf("%I64d\n", x)

#define lowbit(x)   (x)&(-x)

#define Read()  freopen("din.txt", "r", stdin)

#define Write() freopen("dout.txt", "w", stdout)





#define M 1000007

#define N 407

#define ll __int64

using namespace std;

const double eps = 1e-10;

const int inf = 0x7f7f7f7f;



struct node

{

    int v;

    int w;

    int next;

}g[M];

int head[N*N],ct;



struct pnd

{

    int u;

    int ds;

    pnd() {}

    pnd(int x,int y) : u(x),ds(y){}

    bool operator < (const pnd &a) const

    {

        return ds > a.ds;

    }

};



int a[N][N];

int n;



int dis[N*N];

bool vt[N*N];





void add(int u,int v,int w)

{

    g[ct].v = v;

    g[ct].w = w;

    g[ct].next = head[u];

    head[u] = ct++;



    g[ct].v = u;

    g[ct].w = w;

    g[ct].next = head[v];

    head[v] = ct++;



}

//int spfa(int s,int e)

//{

//    int i;

//    for (i = 0; i <= e; ++i)

//    {

//        dis[i] = inf;

//        vt[i] = false;

//    }

//    dis[s] = 0;

//    vt[s] = true;

//    queue<int> Q;

//    Q.push(s);

//    while (!Q.empty())

//    {

//        int u = Q.front(); Q.pop();

//        for (i = head[u]; i != -1; i = g[i].next)

//        {

//            int v = g[i].v;

//            if (dis[v] > dis[u] + g[i].w)

//            {

//                dis[v] = dis[u] + g[i].w;

//                if (!vt[v])

//                {

//                    vt[v] = true;

//                    Q.push(v);

//                }

//            }

//        }

//        vt[u] = false;

//    }

//

//    return dis[e];

//}

int Dijkstra(int s,int e)

{

    priority_queue<pnd> pQ;



    for (int i = 0; i <= e; ++i)

    {

        dis[i] = inf;

        vt[i] = false;

    }

    dis[s] = 0;

    pQ.push(pnd(s,dis[s]));

    while (!pQ.empty())

    {

        pnd ui = pQ.top(); pQ.pop();

        if (vt[ui.u]) continue;

        vt[ui.u] = true;

        for (int i = head[ui.u]; i != -1; i = g[i].next)

        {

            int v = g[i].v;

            if (dis[v] > ui.ds + g[i].w)

            {

                dis[v] = ui.ds + g[i].w;

                pQ.push(pnd(v,dis[v]));

            }

        }

    }

    return dis[e];

}

int main()

{

//    Read();

    int T,i,j;

    scanf("%d",&T);

    while (T--)

    {

        scanf("%d",&n);

        for (i = 0; i < n; ++i)

        for (j = 0; j < n; ++j)

        scanf("%d",&a[i][j]);



        CL(head,-1); ct = 0;

        int s = (n - 1)*(n - 1);

        int e = s + 1;

        int x;

        for (i = 0; i < n; ++i)

        {

            for (j = 0; j < n; ++j)

            {

                if (i == 0 && j != n - 1)

                {

                    x = j;

                    add(s,x,a[i][j]);

                }

                if (j == n - 1 && i != n - 1)

                {

                    x = i*(n - 1) + (n - 2);

                    add(s,x,a[i][j]);

                }



                if (j == 0 && i != n - 1)

                {

                    x = i*(n - 1);

                    add(x,e,a[i][j]);

                }

                if (i == n - 1 && j != n - 1)

                {

                    x = (n - 2)*(n - 1) + j;

                    add(x,e,a[i][j]);

                }



                if (i != n - 1 && j != n - 1)

                {

                    if (i)

                    {

                        x = (i - 1)*(n - 1) + j;

                        add((i*(n - 1) + j),x,a[i][j]);

                    }

                    if (j)

                    {

                        x = i*(n - 1) + j - 1;

                        add((i*(n - 1) + j),x,a[i][j]);

                    }

                }

            }

        }

        //优先队列优化的Dijkstra比spfa快多了。而且spfa时如果s,e链接边的只能是单向,否则会超时

//        printf("<<OL<L\n");

//        printf("%d\n",spfa(s,e));

        printf("%d\n",Dijkstra(s,e));

    }

    return 0;

}
View Code

 

 

你可能感兴趣的:(catch)