这道题,n*m=1000*1000=100 0000
网络流理论上过不了,可是因为数据太弱了,网络流dinic也可以过。
然而这个团队只有我用最短路QAQ。
原题就是一个最小割的典型模型,我们可以把原图的每一个面(三角形)当成一个点,再虚拟一个源和一个汇,拥有上边界或右边界(边界!)的连到源,下边界或左边界的连到汇。有公共边的三角形相连。这样,我最短路中的每一个路径都是一个割。构图很巧妙,把割的权值转移到了最短路的边上。
具体可以搜索:两级相通————浅析最大最小定理在信息学竞赛中的应用 By 周冬
注意要建双向边。当n=1或m=1时特别对待就好了。注意数组大小。
然后最短路算法乱做就可以了。
我用的SPFA:<-却有3000ms 别人网络流才2000ms,不服。
#include<cstdio>
#include<cstdlib>
#include<cstring>
int n,m;
int S,T;
struct mod{int x,y,z,next;};
mod q[6000005];
int first[4000005];
bool v[4000005];
int s[4000005];
int t[4000005];
int len=0;
void ins(int x,int y,int z)
{
len++;
q[len].x=x;
q[len].y=y;
q[len].z=z;
q[len].next=first[x];
first[x]=len;
len++;
q[len].x=y;
q[len].y=x;
q[len].z=z;
q[len].next=first[y];
first[y]=len;
}
int main()
{
scanf("%d%d",&n,&m);
if(n==1||m==1)
{
if(n>m) {int tt=n;n=m;m=tt;}
int ans=999999999;
for(int i=1;i<m;++i)
{
int o;
scanf("%d",&o);
if(o<ans) ans=o;
}
printf("%d\n", ans);
return 0;
}
S=0,T=(n-1)*(m-1)*2+1;
for(int i=0;i<=T;i++)
first[i]=-1;
for(int i=1;i<=n;i++)
for(int j=1;j<m;j++)
{
int o;
scanf("%d",&o);
if(i==1)
ins(S,(i-1)*(m-1)*2+j*2-1,o);
else if (i==n)
ins((i-2)*(m-1)*2+j*2,T,o);
else
ins((i-2)*(m-1)*2+j*2,(i-1)*(m-1)*2+j*2-1,o);
}
for(int i=1;i<n;i++)
for(int j=1;j<=m;j++)
{
int o;
scanf("%d",&o);
if(j==1)
ins((i-1)*(m-1)*2+j*2,T,o);
else if (j==m)
ins(S,(i-1)*(m-1)*2+(j-1)*2-1,o);
else
ins((i-1)*(m-1)*2+(j-1)*2-1,(i-1)*(m-1)*2+j*2,o);
}
for(int i=1;i<n;i++)
for(int j=1;j<m;j++)
{
int o;
scanf("%d",&o);
ins((i-1)*(m-1)*2+j*2-1,(i-1)*(m-1)*2+j*2,o);
}
for(int i=1;i<=T;i++){s[i]=999999999;v[i]=false;}
s[S]=0;
v[S]=true;
t[1]=S;
int st=1,ed=2;
while(st!=ed)
{
int x=t[st];
for(int i=first[x];i!=-1;i=q[i].next)
{
int y=q[i].y;
if(s[x]+q[i].z<s[y])
{
s[y]=s[x]+q[i].z;
if(v[y]==false)
{
v[y]=true;
t[ed]=y;
ed++;
if(ed>T+1)ed=1;
}
}
}
v[x]=false;
st++;
if(st>T+1)st=1;
}
printf("%d\n",s[T]);
}


被折叠的 条评论
为什么被折叠?



