BZOJ 1001

怎么没人写博客了 都闷声发大财啊QAQ

这道题的灵感是某之给我的

看起来是网络流,然而是最短路

对于每一个三角形  抽象成一个点,两点之间边权即为两三角形的边权

然后就是右上角和左下角要特判,右上角连了很多边到右边和上边,左下角同理

跑一边右上角到左下角的最短路

正确性显然

之之好强 Orz

提醒几点:

1、n=1,m=1 特判 相当恶心的一个点

2、数组一定要开够,一定要开够,一定要开够!!!!!

3、中间被我注释掉的是我检查建图正确性,非常有必要!

4、建图太那啥了 自己写的时候就会感觉到深深的恶意!

5、之之太强了

补(By CSC):您的代码空格太多,括号打下面太难看了!!!

补(By WSQ):就是网络流,因为最大流等于最小割,平面图最小割可以用最短路解决

#include<bits/stdc++.h>

using namespace std;

const int maxn=1000100;

int n,m,cnt,head[maxn<<2],vis[maxn<<2],d[maxn<<2];

struct edge
{
	int to,nxt,val;
}e[maxn<<3];

void add(int x,int y,int w)
{
	e[++cnt].to=y;
	e[cnt].nxt=head[x];
	head[x]=cnt;
	e[cnt].val=w;
}

void addedge(int x,int y,int w)
{
	add(x,y,w);
	add(y,x,w);
}

void spfa()
{
	memset(d,0x7f,sizeof(d));
	queue <int> q;
	q.push(0);
	vis[0]=1;
	d[0]=0;
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		vis[x]=0;
		for(int i=head[x];i;i=e[i].nxt)
		{
			int y=e[i].to;
			if(d[y]>d[x]+e[i].val)
			{
				d[y]=d[x]+e[i].val;
				if(!vis[y])
				{
					vis[y]=1;
					q.push(y);
				}
			}
		}
	}
	return ;
}

int main()
{
	scanf("%d%d",&n,&m);
	if(n==1||m==1)
	{
		int x=max(n,m);
		int ans=0x7f;
		for(int i=1;i<x;i++)
		{
			int tmp;
			scanf("%d",&tmp);
			ans=min(ans,tmp);
		}
		printf("%d",ans);
		return 0;
	}
	int maxx=2*(m-1)*(n-1)+1;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<m;j++)
		{
			int w;
			scanf("%d",&w);
			if(i==1)
			{
				addedge(0,j*2,w);
			}
			else if(i==n)
			{
				addedge(maxx,2*(m-1)*(n-2)+2*j-1,w);
			}
			else
			{
				addedge(2*(m-1)*(i-2)+2*j-1,2*(m-1)*(i-1)+2*j,w);
			}
		}
	}
	for(int i=1;i<n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			int w;
			scanf("%d",&w);
			if(j==1)
			{
				addedge(maxx,2*(m-1)*(i-1)+1,w);
			}
			else if(j==m)
			{
				addedge(0,2*(m-1)*(i-1)+2*(m-1),w);
			}
			else
			{
				addedge(2*(m-1)*(i-1)+2*j-2,2*(m-1)*(i-1)+2*j-1,w);
			}
		}
	}
	for(int i=1;i<n;i++)
	{
		for(int j=1;j<m;j++)
		{
			int w;
			scanf("%d",&w);
			addedge(2*(m-1)*(i-1)+2*j-1,2*(m-1)*(i-1)+2*j,w);
		}
	}
	/*for(int i=0;i<=2*(n-1)*(m-1)+1;i++)
	{
		for(int j=head[i];j;j=e[j].nxt)
		{
			printf("%d %d %d\n",e[j].to,i,e[j].val);
		}
	}*/
	spfa();
	printf("%d",d[maxx]);
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值