您的位置:首页 > 其它

BZOJ 1001: [BeiJing2006]狼抓兔子(s-t平面图+最短路求最小割)

2017-07-31 21:58 597 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=1001

题意:



思路:
这道题目是最小割题目,但是吧你直接套用Dinic是会超时的。

这里有种很奇妙的做法啊,具体可以参见论文:《浅析最大最小定理在信息学竞赛中的应用》--周冬

S-T平面图:首先是一平面图(满足欧拉公式与存在对偶图),且源点S,汇点T在边界上。将S-T连线,将最外面的一个大面(无限大)一分为二了,一个为S,一个为T。然后将每条边两边的面相连,权值就是该边权值。最后跑最短路,它经过的路径就是原图中的边,最短路也就变成了最小割。

http://blog.csdn.net/ahero_happy/article/details/6637214该博主讲得不错,可以看一下。

一开始写了个最普通的最短路,结果超时。然后写了带队优化的,超内存了,因为用了vector来存储,最后只好改用数组来存储。

/**************************************************************
Problem: 1001
User: Vortex
Language: C++
Result: Accepted
Time:2112 ms
Memory:89184 kb
****************************************************************/

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn = 1000*1000*2 + 5;

int n, m;
int num;
int src, dst;

struct Edge
{
int v, w;
int next;
}edge[3*maxn];

struct HeapNode
{
int d, u;
HeapNode(int x, int y) :d(x), u(y){}
bool operator < (const HeapNode& rhs) const{
return d > rhs.d;
}
};

int head[maxn];
bool done[maxn];
int d[maxn];

void AddEdges(int u, int v, int w)
{
edge[num].v=v ;edge[num].w=w ;
edge[num].next=head[u] ;head[u]=num++ ;
}

void dijkstra(int s)
{
priority_queue<HeapNode> Q;
for (int i = 0; i <=dst; i++)    d[i] = INF;
d[s] = 0;
memset(done, 0, sizeof(done));
Q.push(HeapNode(0,s));
while (!Q.empty())
{
HeapNode x = Q.top(); Q.pop();
int u = x.u;
if (done[u]) continue;
done[u] = true;
for (int i = head[u]; i!=-1; i=edge[i].next)
{
if (d[edge[i].v] > d[u] + edge[i].w)
{
d[edge[i].v] = d[u] + edge[i].w;
Q.push(HeapNode(d[edge[i].v],edge[i].v));
}
}
}
}

int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
src=0,dst=2*(n-1)*(m-1)+1;

memset(head,-1,sizeof(head));
num=0;

for(int i=1;i<=n;i++)
{
for(int j=1;j<m;j++)
{
int u,v,w;
scanf("%d",&w);
if(i==1)  u=src;
else u=(2*(i-1)-1)*(m-1)+j;
if(i==n)  v=dst;
else v=(2*(i-1))*(m-1)+j;
AddEdges(u,v,w);
AddEdges(v,u,w);
}
}

for(int i=1;i<n;i++)
{
for(int j=1;j<=m;j++)
{
int u,v,w;
scanf("%d",&w);
if(j==1)  u=dst;
else u=(2*(i-1))*(m-1)+j-1;
if(j==m)  v=src;
else v=(2*(i-1))*(m-1)+j-1+m;
AddEdges(u,v,w);
AddEdges(v,u,w);
}
}

for(int i=1;i<n;i++)
{
for(int j=1;j<m;j++)
{
int u,v,w;
scanf("%d",&w);
u=(2*(i-1))*(m-1)+j;
v=(2*(i-1)+1)*(m-1)+j;
AddEdges(u,v,w);
AddEdges(v,u,w);
}
}

dijkstra(src);
printf("%d\n",d[dst]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐