bzoj 1001 狼抓兔子 —— 平面图最小割(最短路)

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1001

平面图最小割可以转化成最短路问题;

建图时看清楚题目的 input ...

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
int const xn=2e6+5,xm=8e6+5;
int n,m,hd[xn],ct,to[xm],nxt[xm],S,T;
ll w[xm],dis[xn],inf=1e17;
bool vis[xn];
struct N{
  int id; ll d;
  N(int i=0,ll d=0):id(i),d(d) {}
  bool operator < (const N &y) const
  {return d>y.d;}
};
priority_queue<N>q;
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
  while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
  return f?ret:-ret;
}
void ade(int x,int y,ll z){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct; w[ct]=z;}
void add(int x,int y,ll z){ade(x,y,z); ade(y,x,z);}
int id(int x,int y,int z){return ((x-1)*(m-1)+(y-1))*2+1+z;}//格子(x,y) 0\1
void dij()
{
  for(int i=S;i<=T;i++)dis[i]=inf;
  dis[S]=0; q.push(N(S,0));
  while(q.size())
    {
      int x=q.top().id; q.pop();
      if(vis[x])continue; vis[x]=1;
      for(int i=hd[x],u;i;i=nxt[i])
      if(dis[u=to[i]]>dis[x]+w[i])
        dis[u]=dis[x]+w[i],q.push(N(u,dis[u]));
    }
}
int main()
{
  n=rd(); m=rd(); S=0; T=id(n-1,m-1,1)+1; ll x;
  if(n<=1||m<=1)
    {
      if(n<=0||m<=0||(n==1&&m==1)){puts("0"); return 0;}
      ll mn=inf;
      if(n==1) for(int i=1;i<m;i++)x=rd(),mn=min(x,mn);
      else if(m==1) for(int i=1;i<n;i++)x=rd(),mn=min(x,mn);
      printf("%lld\n",mn); return 0;
    }
  for(int j=1;j<m;j++)x=rd(),add(T,id(1,j,1),x);
  for(int i=2;i<n;i++)
    for(int j=1;j<m;j++)x=rd(),add(id(i-1,j,0),id(i,j,1),x);
  for(int j=1;j<m;j++)x=rd(),add(id(n-1,j,0),S,x);

  for(int i=1;i<n;i++)
    {
      x=rd(); add(S,id(i,1,0),x);
      for(int j=2;j<m;j++)x=rd(),add(id(i,j-1,1),id(i,j,0),x);
      x=rd(); add(id(i,m-1,1),T,x);
    }

  for(int i=1;i<n;i++)
    for(int j=1;j<m;j++)x=rd(),add(id(i,j,0),id(i,j,1),x);

  dij();
  printf("%lld\n",dis[T]);
  return 0;
}

 

posted @ 2018-12-14 11:54  Zinn  阅读(165)  评论(0编辑  收藏  举报