您的位置:首页 > 其它

BZOJ 1001 狼抓兔子 平面图最小割

2017-08-23 10:57 281 查看
题意:n*m地图 每个点可以走到其右边,下方,右下方.这3道路都有各自的流量限制.

源点s为左上角,终点t为右下角,

n,m<=1000,问最少需要多少个人堵住道路 使得s-t无路径存在.

堵住割上的边 则s-t无路径存在.花费最小也就是求最小割/最大流 n,m<=1e3 TLE...
本图是平面图,平面图的最小割等于其新图的最短路.

新图的点为原图的面.(建新图时对面合理的编号..)

新图边的权值等于:原图中分割这两个面的边的权值. 



#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> ii;
const int inf=0x3f3f3f3f;
const int N=4e6+20;
vector<ii> e
;
int s,t;
int n,m;
void add(int u,int v,int w)
{
e[u].push_back(ii(v,w));
e[v].push_back(ii(u,w));
}
bool inq
;
int dis
;
queue<int> q;
void SPFA(int s,int t)
{
memset(dis,inf,sizeof(dis));
memset(inq,0,sizeof(inq));
dis[s]=0,inq[s]=1,q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop(),inq[u]=0;
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i].first,w=e[u][i].second;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!inq[v])
inq[v]=1,q.push(v);
}
}
}
cout<<dis[t]<<endl;
}
int main()
{
int k;
scanf("%d%d",&n,&m);
s=0,t=(n-1)*(m-1)*2+1;
//ho
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m-1;j++)
{
scanf("%d",&k);
if(i==1) add(j*2,t,k);
else if(i==n) add(s,(n-2)*(m-1)*2+j*2-1,k);
else add((i-2)*(m-1)*2+j*2-1,(i-1)*(m-1)*2+j*2,k);
// int u=(i-2)*(m-1)*2+j*2-1,v=(i-1)*(m-1)*2+j*2;
// cout<<i<<' '<<j<<' '<<u<<' '<<v<<endl;
}
}
//ver
for(int i=1;i<=n-1;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&k);
if (j==1) add((i-1)*(m-1)*2+1,0,k);
else if (j==m) add(t,i*(m-1)*2,k);
else add((i-1)*(m-1)*2+(j-1)*2,(i-1)*(m-1)*2+(j-1)*2+1,k);
}
}

for(int i=1;i<=n-1;i++)
{
for(int j=1;j<=m-1;j++)
{
scanf("%d",&k);
add((i-1)*(m-1)*2+j*2-1,(i-1)*(m-1)*2+j*2,k);
}
}
SPFA(s,t);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: