1. 程式人生 > >bzoj 1001 狼抓兔子 —— 平面圖最小割(最短路)

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; }