1001: [BeiJing2006]狼抓兔子
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 24727 Solved: 6276
[Submit][Status][Discuss]
Description
Input
Output
输出一个整数,表示参与伏击的狼的最小数量.
Sample Input
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
Source
题目大意:在一个n×m的网格图中,要求从(1,1)到(n,m)不连通,那么最少断掉的边权之和。
题解:
直接看是网络流的最小割问题了。但是n×m个点=1000000,边更是3000000条,那么最小割显然不太好。因为是网格图,又是从(1,1)到(n,m)不连通,那么一定是从左边或下边,到上边或右边,那么我们就找一条从左下角到右上角的路径就可以断开连接了。把每一个三角形看成一个点,相邻三角形之间连接一条公共边边权的边,就可以跑最短路了,SPFA和Dij都可以。注意数组不要开小了。
具体见下图:
将每一个三角形编一个号,两个三角形之间连边,再将边界上的三角形连入源点和汇点即可了。
1 #include<queue> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 #define LL long long 8 #define fre(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout); 9 using namespace std; 10 const int MAXN=2500000,INF=0x3f3f3f3f; 11 int n,m,S,T,x,num,CASE; 12 int dis[MAXN]; 13 int head[MAXN],to[MAXN*3],Next[MAXN*3],len[MAXN*3]; 14 bool vis[MAXN]; 15 struct ed 16 { 17 int id,dis; 18 bool operator <(const ed a)const{ 19 return dis>a.dis; 20 } 21 }; 22 void inti(); 23 void add(int f,int t) 24 { 25 Next[++num]=head[f]; 26 to[num]=t; 27 len[num]=x; 28 head[f]=num; 29 } 30 void Dij() 31 { 32 priority_queue<ed>Q; 33 memset(dis,0x3f3f3f3f,sizeof dis); 34 memset(vis,0,sizeof vis); 35 Q.push((ed){S,0}); dis[S]=0; 36 while(!Q.empty()) 37 { 38 ed u=Q.top(); Q.pop(); 39 if(u.id==T)break; 40 vis[u.id]=1; 41 for(int i=head[u.id];i;i=Next[i]) 42 { 43 int v=to[i]; 44 if(vis[v])continue; 45 if(dis[v]>dis[u.id]+len[i]) 46 { 47 dis[v]=dis[u.id]+len[i]; 48 Q.push((ed){v,dis[v]}); 49 } 50 } 51 } 52 } 53 int main() 54 { 55 while(scanf("%d%d",&n,&m)!=EOF) 56 { 57 if(n==m&&n==0)break; 58 num=0; 59 memset(head,0,sizeof head); 60 inti(); 61 Dij(); 62 printf("Case %d: Minimum = %d\n",++CASE,dis[T]); 63 //printf("%d\n",dis[T]); 64 } 65 return 0; 66 } 67 void inti()//连边,比较容易搞错。 68 { 69 S=(n-1)*(m-1)*2+1; T=S+1; 70 for(int i=1;i<=n;i++) 71 for(int j=1;j<m;j++) 72 { 73 scanf("%d",&x); 74 if(i==1) add(j,T),add(T,j); 75 else if(i==n) add(S,(n-1)*(m-1)*2-(m-1)+j),add((n-1)*(m-1)*2-(m-1)+j,S); 76 else 77 { 78 int a=(i-1)*(m-1)*2-(m-1)+j; 79 int b=a+(m-1); 80 add(a,b); add(b,a); 81 } 82 } 83 for(int i=1;i<n;i++) 84 for(int j=1;j<=m;j++) 85 { 86 scanf("%d",&x); 87 if(j==1) add(S,(i-1)*(m-1)*2+(m-1)+1),add((i-1)*(m-1)*2+(m-1)+1,S); 88 else if(j==m) add((i-1)*(m-1)*2+(m-1),T),add(T,(i-1)*(m-1)*2+(m-1)); 89 else 90 { 91 int a=(i-1)*(m-1)*2+(j-1); 92 int b=a+1+(m-1); 93 add(a,b); add(b,a); 94 } 95 } 96 for(int i=1;i<n;i++) 97 for(int j=1;j<m;j++) 98 { 99 scanf("%d",&x); 100 int a=(i-1)*(m-1)*2+j; 101 int b=a+(m-1); 102 add(a,b); add(b,a); 103 } 104 }