bzoj1001
spfa--周冬《两极相通——浅析最大—最小定理在信息学竞赛中的应用》
虽然是网络流最小割,但是我们可以转换一下,转成最短路
简单点讲,每个平面图都对应一个对偶图,对偶图中的最小环就是原图的最小割,如果删去对偶图中s-t这条边,就是相当于求最短路了!
建图十分玄学,建完后跑一遍spfa就好了。
#include <stdio.h> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <stack> using namespace std; const int inf=2147483647; const int maxn=2000010; struct hh { int u,v,w,next; }e[maxn*3]; int n,m,point; int head[maxn],dis[maxn],vis[maxn]; template <class T> void read(T&x) { x=0;char c=getchar();int f=0; while(c<'0'||c>'9'){f|=(c=='-');c=getchar();} while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar(); x=f?-x:x; } void spfa(int s) { queue<int>q; memset(dis,0x7f/2,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[s]=0;q.push(s);vis[s]=1; while(!q.empty()) { int x=q.front();q.pop();vis[x]=0; for(int i=head[x];i!=-1;i=e[i].next) { int y=e[i].v; if(dis[y]>dis[x]+e[i].w) { dis[y]=dis[x]+e[i].w; if(!vis[y]) { q.push(y); vis[y]=1; } } } } return; } void add(int u,int v,int w) { e[++point].u=u;e[point].v=v;e[point].w=w;e[point].next=head[u];head[u]=point; e[++point].u=v;e[point].v=u;e[point].w=w;e[point].next=head[v];head[v]=point; } int main() { memset(head,-1,sizeof(head)); read(n);read(m); if (n == 1 || m == 1) { if (n > m) swap(n, m); int ans = inf; for (int i = 1; i < m; ++i) { int x; read(x); if (x < ans) ans = x; } printf("%d\n", ans); exit(0); } int S=0,T=2*(m-1)*(n-1)+1; int w; for(int j=1;j<m;j++) { int id=j*2-1; read(w); add(S,id,w); } for(int i=1;i<n-1;i++) { for(int j=1;j<m;j++) { int t1=2*((i-1)*(m-1)+j); int t2=2*(i*(m-1)+j)-1; read(w); add(t1,t2,w); } } for(int j=1;j<m;j++) { int id=2*((n-2)*(m-1)+j); read(w); add(id,T,w); } //横向边 for(int i=0;i<n-1;i++) { for(int j=1;j<=m;j++) { scanf("%d",&w); if(j==1)//与终点相连 { int id=2*(i*(m-1)+j); add(id,T,w); } else if(j==m) { int id=2*((i+1)*(m-1))-1; add(S,id,w); } else { int t1=2*(i*(m-1)+j-1)-1; int t2=2*(i*(m-1)+j); add(t1,t2,w); } } } //纵向 for(int i=0;i<n-1;i++) { for(int j=1;j<m;j++) { read(w); int t1=2*(i*(m-1)+j)-1; int t2=2*(i*(m-1)+j); add(t1,t2,w); } } //斜向 spfa(0); printf("%d",dis[T]); return 0; }