hdu3870-Catch the Theves(平面图最小割)

本文介绍了一种利用平面图最小割算法解决特定路径问题的方法。该问题设定为一群盗贼从城市A到城市B,途中可能经过多个路径,任务是找出拦截所有盗贼的最低成本路径。文章详细阐述了如何通过构建图模型并使用最短路径算法来找到这个最小割,最终确定拦截所有盗贼所需的最低成本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

解析:平面图最小割,把面当成点,然后用最短路求最小割,详见百度

代码

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef __int64 LL;
const LL INF=1000000000000007;
const int maxn=2*402*402;
int N,eid,head[maxn];
struct edge{ int v,w,next; }E[4*maxn];
void AddEdge(int u,int v,int w)
{
    E[++eid].v=v; E[eid].w=w; E[eid].next=head[u]; head[u]=eid;
    E[++eid].v=u; E[eid].w=w; E[eid].next=head[v]; head[v]=eid;
}
int f(int x,int y){ return x*(N-1)+y; }
struct node
{
    int u;
    LL d;
    node(int u=0,LL d=0):u(u),d(d){}
    bool operator < (const node& t) const{ return d>t.d; }
};
priority_queue<node> que;
LL D[maxn];
bool vis[maxn];
int Dij(int S,int T)
{
    while(!que.empty()) que.pop();
    for(int i=0;i<maxn;i++) D[i]=INF;
    D[S]=0;
    memset(vis,false,sizeof(vis));
    que.push(node(S,0));
    while(!que.empty())
    {
        node t=que.top(); que.pop();
        int u=t.u;
        if(vis[u]) continue;
        vis[u]=true;
        for(int i=head[u];i!=-1;i=E[i].next)
        {
            edge& e=E[i];
            int v=e.v,w=e.w;
            if(D[v]>D[u]+w)
            {
                D[v]=D[u]+w;
                que.push(node(v,D[v]));
            }
        }
    }
    return D[T];
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&N);
        int s=0,t=(N-1)*(N-1)+1;
        memset(head,-1,sizeof(head));
        eid=0;
        int u,v,w;
        for(int i=1;i<=N;i++)
            for(int j=1;j<=N;j++)
        {
            scanf("%d",&w);
            if(i==1&&j<N)
            {
                u=s; v=j;
                AddEdge(u,v,w);
            }
            if(i==N&&j<N)
            {
                u=f(i-2,j); v=t;
                AddEdge(u,v,w);
            }
            if(1<i&&i<N&&j<N)
            {
                u=f(i-2,j);
                v=f(i-1,j);
                AddEdge(u,v,w);
            }
            if(j==1&&i<N)
            {
                u=f(i-1,j); v=t;
                AddEdge(u,v,w);
            }
            if(j==N&&i<N)
            {
                u=f(i-1,j-1); v=s;
                AddEdge(u,v,w);
            }
            if(1<j&&j<N&&i<N)
            {
                u=f(i-1,j-1);
                v=f(i-1,j);
                AddEdge(u,v,w);
            }
        }
        printf("%d\n",Dij(s,t));
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/wust-ouyangli/p/5794452.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值