前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >752. [BJOI2006] 狼抓兔子

752. [BJOI2006] 狼抓兔子

作者头像
attack
发布2018-04-13 15:46:40
7273
发布2018-04-13 15:46:40
举报

★★★   输入文件: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

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 }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-07-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Description   Source: Beijing2006 [BJOI2006]
  • Input
  • Output
  • Sample Input
  • Sample Output
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档