752. [BJOI2006] 狼抓兔子
★★★ 输入文件:bjrabbit.in
输出文件:bjrabbit.out
简单对比
时间限制:1 s 内存限制:162 MB
Description Source: Beijing2006 [BJOI2006]
八中OJ上本题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦.
Input
第一行为N,M.表示网格的大小,N,M均小于等于1000.接下来分三部分 第一部分共N行,每行M-1个数,表示横向道路的权值. 第二部分共N-1行,每行M个数,表示纵向道路的权值. 第三部分共N-1行,每行M-1个数,表示斜向道路的权值. 输入文件保证不超过10M
Output
输出一个整数,表示参与伏击的狼的最小数量.
Sample Input
3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
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
14
如果你想到了一个定理:
最大流==最小割,
然后聪明的想到了Dinic跑最大流
那么恭喜你,
被坑了,。。,
因为这道题的数据范围比较大
Dinic肯定跑步过去,
所以考虑用对偶图跑最短路,
至于为什么,,,我也不太懂,,
特别是代码。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #define inf 0x7fffffff 9 using namespace std; 10 const int maxn=2000000+10; 11 const int M = maxn*3+10; 12 13 int n,m,nn,mm; 14 int from,to; 15 struct Edge 16 { 17 int v,flow; 18 int next; 19 }edge[M]; 20 int head[maxn],edgenum; 21 22 void add(int u,int v,int flow) 23 { 24 edge[edgenum].v=v ;edge[edgenum].flow=flow ; 25 edge[edgenum].next=head[u] ;head[u]=edgenum++ ; 26 27 edge[edgenum].v=u ;edge[edgenum].flow=flow ; 28 edge[edgenum].next=head[v] ;head[v]=edgenum++ ; 29 } 30 31 struct node 32 { 33 int v,w; 34 friend bool operator < (node a,node b) 35 { 36 return a.w > b.w; 37 } 38 }cur,tail; 39 int d[maxn],vis[maxn]; 40 void Dijkstra(int from,int to) 41 { 42 for (int i=0 ;i<maxn ;i++) d[i]=inf; 43 memset(vis,0,sizeof(vis)); 44 d[from]=0; 45 priority_queue<node> Q; 46 cur.v=from ;cur.w=0 ; 47 Q.push(cur); 48 while (!Q.empty()) 49 { 50 cur=Q.top() ;Q.pop() ; 51 int x=cur.v; 52 if (vis[x]) continue; 53 vis[x]=1; 54 for (int i=head[x] ;i!=-1 ;i=edge[i].next) 55 { 56 if (d[edge[i].v ]>d[x]+edge[i].flow) 57 { 58 d[edge[i].v ]=d[x]+edge[i].flow; 59 tail.v=edge[i].v; 60 tail.w=d[edge[i].v ]; 61 Q.push(tail); 62 } 63 } 64 } 65 printf("%d\n",d[to]); 66 } 67 68 int main() 69 { 70 while (scanf("%d%d",&n,&m)!=EOF) 71 { 72 memset(head,-1,sizeof(head)); 73 edgenum=0; 74 from=0; 75 to=2*(n-1)*(m-1)+1; 76 int x,y,cost; 77 for (int i=1 ;i<=n ;i++) 78 { 79 for (int j=1 ;j<m ;j++) 80 { 81 scanf("%d",&cost); 82 x= i==1 ? from : (2*(i-1)-1)*(m-1)+j; 83 y= i==n ? to : (2*(i-1))*(m-1)+j; 84 add(x,y,cost); 85 } 86 } 87 for (int i=1 ;i<n ;i++) 88 { 89 for (int j=1 ;j<=m ;j++) 90 { 91 scanf("%d",&cost); 92 x= j==1 ? to : (2*(i-1))*(m-1)+j-1; 93 y= j==m ? from : (2*(i-1))*(m-1)+j-1+m; 94 add(x,y,cost); 95 } 96 } 97 for (int i=1 ;i<n ;i++) 98 { 99 for (int j=1 ;j<m ;j++) 100 { 101 scanf("%d",&cost); 102 x=(2*(i-1))*(m-1)+j; 103 y=(2*(i-1)+1)*(m-1)+j; 104 add(x,y,cost); 105 } 106 } 107 Dijkstra(from,to); 108 } 109 return 0; 110 }
下面是自己写的蜜汁WA、、
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<queue> 6 #include<algorithm> 7 using namespace std; 8 const int MAXN=6000002; 9 const int MAXM=6000002; 10 const int maxn=0x7fffffff; 11 inline void read(int &n) 12 { 13 char c='+';int x=0;bool flag=0; 14 while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;} 15 while(c>='0'&&c<='9'){x=x*10+(c-48);c=getchar();} 16 flag==1?n=-x:n=x; 17 } 18 struct node 19 { 20 int u,v,f,nxt; 21 }edge[MAXM]; 22 int head[MAXN]; 23 int num=1; 24 int n,m; 25 int dis[MAXN]; 26 bool vis[MAXN]; 27 inline void add_edge(int x,int y,int z) 28 { 29 edge[num].u=x; 30 edge[num].v=y; 31 edge[num].f=z; 32 edge[num].nxt=head[x]; 33 head[x]=num++; 34 } 35 inline void SPFA(int s,int t) 36 { 37 for(int i=0;i<t;i++) 38 dis[i]=maxn; 39 dis[s]=0; 40 vis[s]=1; 41 queue<int>q; 42 q.push(s); 43 while(q.size()!=0) 44 { 45 int p=q.front(); 46 q.pop(); 47 vis[p]=0; 48 for(int i=head[p];i!=-1;i=edge[i].nxt) 49 { 50 if(dis[edge[i].v]>dis[edge[i].u]+edge[i].f) 51 { 52 dis[edge[i].v]=dis[edge[i].u]+edge[i].f; 53 if(vis[edge[i].v]==0) 54 { 55 vis[edge[i].v]=1; 56 q.push(edge[i].v); 57 } 58 } 59 } 60 } 61 printf("%d",dis[t]); 62 } 63 int main() 64 { 65 //freopen("bjrabbit.in","r",stdin); 66 //freopen("bjrabbit.out","w",stdout); 67 read(n);read(m); 68 memset(head,-1,sizeof(head)); 69 int from=0; 70 int to=(2*(n-1)*(m-1))+1; 71 int spend,x,y; 72 for(int i=1;i<=n;i++) 73 for(int j=1;j<m;j++) 74 { 75 read(spend); 76 x= i==1? from: (2*(i-1)-1)*(m-1)+j; 77 y= i==n? to : (2*(i-1))*(m-1)+j; 78 // printf("%d %d %d \n",x,y,spend); 79 add_edge(x,y,spend); 80 add_edge(y,x,spend); 81 } 82 for(int i=1;i<n;i++) 83 for(int j=1;j<=m;j++) 84 { 85 read(spend); 86 x= j==1?to:(2*(i-1))*(m-1)+j-1; 87 y= j==m?from:(2*(i-1))*(m-1)+j-1+m; 88 //printf("%d %d %d \n",x,y,spend); 89 add_edge(x,y,spend); 90 add_edge(y,x,spend); 91 } 92 for(int i=1;i<n;i++) 93 for(int j=1;j<m;j++) 94 { 95 read(spend); 96 x=(2*(i-1))*(m-1)+j; 97 y=(2*(i-1)+1)*(m-1)+j; 98 //printf("%d %d %d \n",x,y,spend); 99 add_edge(x,y,spend); 100 add_edge(y,x,spend); 101 } 102 SPFA(from,to); 103 return 0; 104 }
作者:自为风月马前卒
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。