怎么没人写博客了 都闷声发大财啊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]);
}