bzoj1001

来源:互联网 发布:有马贵将 知乎 编辑:程序博客网 时间:2024/05/19 20:22

这道题,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]);}



0 0
原创粉丝点击