hdu 3870 最小割转化为最短路径2

Catch the Theves

Problem Description

A group of thieves is approaching a museum in the country of zjsxzy,now they are in city A,and the museum is in city B,where keeps many broken legs of zjsxzy.Luckily,GW learned the conspiracy when he is watching stars and told it to zjsxzy.
Zjsxzy decided to caught these thieves,and he let the police to do this,the police try to catch them on their way from A to B. Although the thieves might travel this way by more than one group, zjsxzy‘s excellent police has already gather the statistics that the cost needed on each road to guard it. 
Now ,zjsxzy‘s conutry can be described as a N*N matrix A,Aij indicates the city(i,j) have bidirectionals road to city(i+1,j) and city(i,j+1),gurad anyone of them costs Aij.
Now give you the map,help zjsxzy to calculate the minimium cost.We assume thieves may travel in any way,and we will catch all passing thieves on a road if we guard it.

Input

The first line is an integer T,followed by T test cases.
In each test case,the first line contains a number N(1<N<=400).
The following N lines,each line is N numbers,the jth number of the ith line is Aij.
The city A is always located on (1,1) and the city B is always located on (n,n).
Of course,the city (i,j) at the last row or last line won‘t have road to (i,j+1) or (i+1,j).

Output

For each case,print a line with a number indicating the minimium cost to arrest all thieves.

Sample Input

1

3

10 5 5

6 6 20

4 7 9

Sample Output

18

hint 

The map is like this:


思路:和上一题http://www.cnblogs.com/EdsonLin/p/5574033.html差不多,不过这一题直接给了点权,所以逻辑上感觉好理解一点吧

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <stack>
#include <string>
#include <queue>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;

//#define EdsonLin

#ifdef EdsonLin
#define debug(...) fprintf(stderr,__VA_ARGS__)
#else
#define debug(...)
#endif //EdsonLin

typedef long long ll;
typedef double db;
const int inf = 0x3f3f3f;
const int MAXN = 410;
const int MAXNN = 160000;
const int MAXM = 1e6;
//const int MAXM = 3e4+100;
const int MOD = 1000000007;
const db eps = 1e-3;
#define PB push_back

struct dij{
    int n,m;
    int first[MAXNN];
    struct edge{
        int st,to,next,dist;
    };
    vector<edge>e;
    int top;
    int d[MAXNN]; //s到各节点的距离
    int done[MAXNN]; //是否已经被永久标记
    int p[MAXNN]; //记录上一条边
    struct heapnode{
        int st;
        int dist;
        bool operator < (const heapnode& rhs) const {
            return dist>rhs.dist;
        }
    };
    void init(int n){
        this->n = n;
        memset(first,-1,sizeof(first));
        top = 0;
        e.clear();
    }
    void addedge(int u,int v,int dist){
        /*e[top].st = u;
        e[top].to = v;
        e[top].dist = dist;
        e[top].next = first[u];
        first[u] = top++;*/
        edge a;
        a.st = u;
        a.to = v;
        a.dist = dist;
        a.next  = first[u];
        e.PB(a);
        first[u] = top++;
        //cout<<first[u]<<endl;
        //cout<<top<<endl;
    }

    void pqdij(int s){
        priority_queue<heapnode>Q;
        heapnode a;
        for(int i=0;i<n;i++)
            d[i] = inf;
        d[s] = 0;
        memset(done,0,sizeof(done));
        a.dist = 0;
        a.st = s;
        Q.push(a);
        while(!Q.empty()){
            heapnode x = Q.top();
            Q.pop();
            int u = x.st;
            if(done[u])continue;
            done[u] = 1;
            for(int i=first[u];i!=-1;i=e[i].next){
                if(d[e[i].to]>d[u]+e[i].dist){
                    d[e[i].to] = d[u] + e[i].dist;
                    p[e[i].to] = i;
                    a.dist = d[e[i].to];
                    a.st = e[i].to;
                    Q.push(a);
                }
            }
        }
    }
}solver;

int readint(){int x;scanf("%d",&x);return x;}

int main()
{
    #ifdef EdsonLin
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        int _time_ed = clock();
    #endif //EdsonLin

    int T;
    scanf("%d",&T);
    int mc=0,grid[MAXN][MAXN];
    while(mc++<T){
        int n,st,ed;
        cin>>n;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++)
                grid[i][j] = readint();
        }
        st = 0;ed = (n-1)*(n-1)+1;
        solver.init(ed+1);
        for(int i=1;i<n;i++){
            for(int j=1;j<n;j++){
                int cur = (i-1)*(n-1)+j;
                if(i==1){
                    solver.addedge(cur,ed,grid[i][j]);
                    solver.addedge(ed,cur,grid[i][j]);
                }
                if(i!=n-1){
                    solver.addedge(cur,cur+n-1,grid[i+1][j]);
                    solver.addedge(cur+n-1,cur,grid[i+1][j]);
                }
                if(i==n-1){
                    solver.addedge(st,cur,grid[i+1][j]);
                    solver.addedge(cur,st,grid[i+1][j]);
                }
                if(j==1){
                    solver.addedge(st,cur,grid[i][j]);
                    solver.addedge(cur,st,grid[i][j]);
                }
                if(j!=n-1){
                    solver.addedge(cur,cur+1,grid[i][j+1]);
                    solver.addedge(cur+1,cur,grid[i][j+1]);
                }
                if(j==n-1){
                    solver.addedge(cur,ed,grid[i][j+1]);
                    solver.addedge(ed,cur,grid[i][j+1]);
                }
            }
        }
        solver.pqdij(st);
        printf("%d\n",solver.d[ed]);
    }

    #ifdef EdsonLin
        debug("time: %d\n",int(clock()-_time_ed));
    #endif //EdsonLin
   // cout << "Hello world!" << endl;
    return 0;
}

时间: 2024-10-05 23:15:01

hdu 3870 最小割转化为最短路径2的相关文章

UVALive 3661 最小割转化为最短路径

题意:动物逃跑,从左上跑到右下角,逃跑的路径是一个grid的边,现在动物园的工作人员要去拦截.input给出了grid每条路径拦截所需要的cost,题目要求拦截成功最小的成本. 经典的最小割问题,但是400*400个点太大了,所以不能直接这么做 lrj给出的方法是动物要从左上跑到右下,所有我们考虑怎么摆障碍物就可以了,思考可以知道,只要做左/下->右/上的连续拦截边,就可以将所有可行路径分割开.如下图(偷了别人博客的图...) 这张图其实是hdu3870的图,题意差不多,但是没有斜边,所以少了两

hdu 3657 最小割的活用 / 奇偶方格取数类经典题 /最小割

题意:方格取数,如果取了相邻的数,那么要付出一定代价.(代价为2*(X&Y))(开始用费用流,敲升级版3820,跪...) 建图:  对于相邻问题,经典方法:奇偶建立二分图.对于相邻两点连边2*(X&Y),源->X连边,Y->汇连边,权值w为点权. ans=总点权-最小割:如果割边是源->X,表示x不要选(是割边,必然价值在路径上最小),若割边是Y-汇点,同理:若割边是X->Y,则表示选Y点且选X点, 割为w( 2*(X&Y) ). 自己的确还没有理解其本质

There is a war (hdu 2435 最小割+枚举)

There is a war Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 970    Accepted Submission(s): 277 Problem Description There is a sea. There are N islands in the sea. There are some directional

hdu 3204(最小割--关键割边)

Ikki's Story I - Road Reconstruction Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 7491   Accepted: 2172 Description Ikki is the king of a small country – Phoenix, Phoenix is so small that there is only one city that is responsible fo

hdu 5076 最小割灵活的运用

题意比较复杂,其实关键是抽象出来:每个点,可以赋予俩个值(二选一,必需选一个,设ai,bi).  求所有之和最大,有条件:若俩个点同时满足: 1,:点的二进制只有一位不同.  2:至少有一个是选B值: 则可获得对应加成. 这题开始想了半天,建图遇到问题,看了官方说是最小割,于是入手: a值就是小于阈值的最大值,B值就是大于等于的最大值. 思路:俩个点选其一,必然想到建二分(每个点一分为二)图,中间连无穷的边.因为只有一位不同,必然分奇偶点,有奇数个1的点,源点到他为A值,对应点到汇点为B值,偶点

hdu 1565 最小割

黑白染色,源指向白,黑指向汇,容量都是方格中数的大小,相邻的格子白指向黑,容量为oo,然后求一次最小割. 这个割是一个简单割,如果只选择不在割中的点,那么一种割就和一个选数方案一一对应,割的大小就是不选的那些数的大小,我们需要最小化这个值. 答案=总和-最小割 1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <vector> 5 #define maxn 410 6

Being a Hero (hdu 3251 最小割 好题)

Being a Hero Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1211    Accepted Submission(s): 381 Special Judge Problem Description You are the hero who saved your country. As promised, the ki

HDU 3526 最小割

点击打开链接 题意:有两个公司分别提供的n个部件,每个部件的价格给出,现在要这买n个部件,我可以选择两个公司中的任意一个,但是对于下面给的m个关系来说,若满足i与j不再同一个公司,那么就要加上c的费用,问买n个部件的最小花费 思路:刚刚读完题的时候感觉像是最小费用流呐,流量就是5呗,然后根据关系建图,画了一会也画不出来,看了一下正解竟然是最小割,思想到时很简单,但是思路不对的话还是很难想到的,建图就是源点,中间一列n个部件,然后汇点,源点连中间的话就是A公司的n个物品,然后中间连汇点的话就是B公

hdu 1569 最小割

和HDU 1565是一道题,只是数据加强了,貌似轮廓线DP来不了了. 1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <vector> 5 #define maxn 2510 6 #define oo 0x3f3f3f3f 7 using namespace std; 8 9 struct Edge { 10 int u, v, f; 11 Edge( int u,