★★★ 输入文件:bjrabbit.in
输出文件:bjrabbit.out
简单对比
时间限制:1 s 内存限制:162 MB
八中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只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦.
第一行为N,M.表示网格的大小,N,M均小于等于1000.接下来分三部分 第一部分共N行,每行M-1个数,表示横向道路的权值. 第二部分共N-1行,每行M个数,表示纵向道路的权值. 第三部分共N-1行,每行M-1个数,表示斜向道路的权值. 输入文件保证不超过10M
输出一个整数,表示参与伏击的狼的最小数量.
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
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 }