http://www.lydsy.com/JudgeOnline/problem.php?id=2007
思路:
显然海拔是一片0,另一片1,答案就是01的分界线的流量。
本题中的图是平面图,所以求最小割的时候,可以转换成对偶图最短路,据Gword说:有向边就统一让它顺时针旋转90°,还有,要先将S和T连边,来"劈开"最外面的空白,然后再把S和T分开。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #include<queue> 7 using namespace std; 8 int first[250005],next[2000005],go[2000005],tot,val[2000005]; 9 int dis[250005],vis[250005],S,T,n; 10 int read(){ 11 char ch=getchar();int t=0,f=1; 12 while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();} 13 while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();} 14 return t*f; 15 } 16 void insert(int x,int y,int z){ 17 tot++; 18 go[tot]=y; 19 next[tot]=first[x]; 20 first[x]=tot; 21 val[tot]=z; 22 } 23 void add(int x,int y,int z){ 24 insert(x,y,z); 25 } 26 int id(int x,int y){ 27 if (x==0||y==n+1) return T; 28 if (x==n+1||y==0) return S; 29 return (x-1)*n+y; 30 } 31 void dijkstra(){ 32 memset(dis,127/3,sizeof dis); 33 priority_queue< pair<int,int> ,vector< pair<int,int> > ,greater<pair<int,int> > > Q; 34 dis[S]=0; 35 Q.push(make_pair(0,S)); 36 while (!Q.empty()){ 37 int now=Q.top().second;Q.pop(); 38 if (vis[now]) continue; 39 vis[now]=1; 40 for (int i=first[now];i;i=next[i]){ 41 int pur=go[i]; 42 if (dis[pur]>dis[now]+val[i]){ 43 dis[pur]=dis[now]+val[i]; 44 Q.push(make_pair(dis[pur],pur)); 45 } 46 } 47 } 48 } 49 int main(){ 50 n=read(); 51 S=0,T=n*n+1; 52 for (int i=1;i<=n+1;i++) 53 for (int j=1;j<=n;j++) 54 add(id(i,j),id(i-1,j),read()); 55 for (int i=1;i<=n;i++) 56 for (int j=1;j<=n+1;j++) 57 add(id(i,j-1),id(i,j),read()); 58 for (int i=1;i<=n+1;i++) 59 for (int j=1;j<=n;j++) 60 add(id(i-1,j),id(i,j),read()); 61 for (int i=1;i<=n;i++) 62 for (int j=1;j<=n+1;j++) 63 add(id(i,j),id(i,j-1),read()); 64 dijkstra(); 65 printf("%d\n",dis[T]); 66 }
时间: 2024-11-09 00:52:55