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

来源:互联网 发布:js给div的value赋值 编辑:程序博客网 时间:2024/05/21 19:21

题意: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[N];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[N];int dis[N];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;}}//verfor(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;}



阅读全文
0 0