UVA1376 Animal Run 平面图+最短路

此题关键字: 平面图 , 点带权图  , 最小割转化成最短路。

难点是建图复杂、、

另外之前普通的dijTLE后来改成加了堆的就过了。

写完后看了标程。刘汝佳给出的代码的最短路模板写的很漂亮,用了STL的堆,看看自己的模板,实在太多了。。。

Time Limit: 6000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu

[]   [Go Back]   [Status]  

Description

Download as PDF

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.

\epsfbox{p3661.eps}

Figure 1: This is a  x 4 nodes grid, the number beside the path indicating how many staff shall be sent to block this path

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$ \leq$ nm $ \leq$ 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

For each case, output how many staff at least shall be sent to block all animals. Please output in the following format.

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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值