此题关键字: 平面图 , 点带权图 , 最小割转化成最短路。
难点是建图复杂、、
另外之前普通的dijTLE后来改成加了堆的就过了。
写完后看了标程。刘汝佳给出的代码的最短路模板写的很漂亮,用了STL的堆,看看自己的模板,实在太多了。。。
Time Limit: 6000MS | Memory Limit: Unknown | 64bit IO Format: %lld & %llu |
Description

Animals are living their painful lives in the zoo. Their activities are limited in a small area without any fun of snacks, alcohol, love or games. They are so upset that they decide to escape in a night.
As shown in Figure 1, the paths in the zoo can be expressed by a grid with n x m nodes. All the paths in the grid are two-way, horizontal or vertical or diagonal. Animals start from the upper left corner, and they are free if they can reach the lower right through paths.

To protect public safety, the police are sent to block some paths to catch all the escaping animals. As it needs certain police staff to block a path, you are required to write a program for the police officer, and tell him how many staff at least shall be sent in order to defeat this Animal Escape.
Input
Input contains several cases, each describes one escape action.
Each case begins with two integers n and m, 3 n, m
1000.
For the following n lines, there are m - 1 integers in each line, indicating how many staff shall be sent to block the horizontal paths respectively.
For the following n - 1 lines, there are m integers in each line, indicating how many staff shall be sent to block the vertical paths respectively.
For the following n - 1 lines, there are m - 1 integers in each line, indicating how many staff shall be sent to block the diagonal paths respectively.
Each line describes the paths from left to right. All integers in input file are no more than 1, 000, 000.
The last case is followed by a line containing two zeros. The size of the input data is about 16MB.
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 0 0
Sample Output
Case 1: Minimum = 14
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 1005*1005*3
struct node{
int to,dis,next;
}e[50000000];
bool visited[MAXN];
int dis[MAXN],g[MAXN],num;
int m,n;
void add(int a,int b,int c){
e[num].to=b;
e[num].dis=c;
e[num].next=g[a];
g[a]=num++;
}
bool cmp(node a,node b){
return a.dis<b.dis;
}
class heap{
public:
int min(int x,int y){
return a[x].dis<a[y].dis?x:y;
}
void push(node e){
for(i=++n;i>1 && cmp(e,a[i>>1]);i>>=1)
a[i]=a[i>>1];
a[i]=e;
}
void pop(){
node e=a[n];
for(i=2;i<n;i<<=1){
if(i<n-1)
i=min(i,i+1);
if(cmp(e,a[i]))
break;
a[i>>1]=a[i];
}
a[i>>1]=a[n--];
}
node top(){
return a[1];
}
bool empty(){
return !n;
}
void clear(){
n=0;
}
private:
node a[MAXN];
int n,i;
};
heap h;
int dijkstra(int s,int n){
node temp;
int tag;
h.clear();
for(int i=0;i<=n;i++){
visited[i]=false;
dis[i]=INF;
}
dis[s]=0;
temp.to=s;
temp.dis=0;
h.push(temp);
while(!h.empty()){
tag=h.top().to;
h.pop();
if(!visited[tag]){
visited[tag]=true;
for(int i=g[tag];i!=-1;i=e[i].next){
int j=e[i].to;
if(!visited[j] && dis[j]>dis[tag]+e[i].dis){
dis[j]=dis[tag]+e[i].dis;
temp.to=j;
temp.dis=dis[j];
h.push(temp);
}
}
}
}
}
int row[1100][1100];
int col[1100][1100];
int cro[1100][1100];
#define base1 0
#define base2 n*(m-1)
#define base3 n*(m-1)+(n-1)*m
#define total n*(m-1)+(n-1)*m+(n-1)*(m-1)
//上三角建图
void UP(int i,int j){
int p1=(i-1)*(m-1)+j;
int x1,y1,x2,y2;
int p2,p3;
x1=i-1,y1=j; // 相应对角线坐标
x2=i-1,y2=j; // 相应竖直线坐标
p2=base3+(x1-1)*(m-1)+y1;
p3=base2+(x2-1)*m+y2;
add(p1,p2,cro[x1][y1]);
add(p3,p2,cro[x1][y1]);
add(p1,p3,col[x2][y2]);
add(p2,p3,col[x2][y2]);
add(p2,p1,row[i][j]);
add(p3,p1,row[i][j]);
}
//下三角建图
void DOWN(int i,int j){
int p1=(i-1)*(m-1)+j;
int x1,y1,x2,y2;
int p2,p3;
x1=i,y1=j; // 相应对角线坐标
x2=i,y2=j+1; // 相应竖直线坐标
p2=base3+(x1-1)*(m-1)+y1;
p3=base2+(x2-1)*m+y2;
add(p1,p2,cro[x1][y1]);
add(p3,p2,cro[x1][y1]);
add(p1,p3,col[x2][y2]);
add(p2,p3,col[x2][y2]);
add(p3,p1,row[i][j]);
add(p2,p1,row[i][j]);
}
int main(){
int cs=1;
while(~scanf("%d%d",&n,&m)){
if(n+m==0) break;
//n*(m-1) 节点编号:1 - n*(m-1)
for(int i=1;i<=n;i++)
for(int j=1;j<m;j++) scanf("%d",&row[i][j]);
//(n-1)*m 节点编号:n*(m-1)+1 - n*(m-1)+(n-1)*m
for(int i=1;i<n;i++)
for(int j=1;j<=m;j++) scanf("%d",&col[i][j]);
//(n-1)*(m-1) 节点编号:n*(m-1)+(n-1)*m+1 - n*(m-1)+(n-1)+(n-1)*(m-1)
for(int i=1;i<n;i++)
for(int j=1;j<m;j++) scanf("%d",&cro[i][j]);
memset(g,-1,sizeof(g));num=0;
//建立点带权图,以三角形为单位建图,以行为基准,最上 和 最下两条边界特殊处理
for(int i=1;i<m;i++)
UP(n,i),DOWN(1,i);
for(int i=2;i<n;i++)
for(int j=1;j<m;j++)
UP(i,j),DOWN(i,j);
for(int i=1;i<m;i++)
add(0,(n-1)*(m-1)+i,row[n][i]);
for(int i=1;i<n;i++)
add(0,base2+(i-1)*m+1,col[i][1]);
dijkstra(0,total);
int ans=INF;
for(int i=1;i<m;i++)
ans=min(ans,dis[i]);
for(int i=1;i<n;i++)
ans=min(ans,dis[base2+(i-1)*m+m]);
printf("Case %d: Minimum = %d\n",cs++,ans);
}
return 0;
}