裸的最小割,就是如果用邻接矩阵存的话点的数目有点儿大=。 =
逼得我这种懒的要死的邻接矩阵忠实拥护者把自己的模板改成了临界表。。。。值得纪念。。
当时觉得反正模板改都改了 ,不如再偷窥一下lieyan大神的代码看看有没有能优化的地方。。。
结果就从6000+ms优化到了100+ms......
orz烈焰学长。。。
长大了我也要写这种可读性又强效率又高的代码
题目链接:http://cstest.scu.edu.cn/soj/problem.action?id=3107
题意:n*m 个方格,每个方格中有一个不大于 100000 的正整数。从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。
算法:
还是给方格交替染色,划分成X类点和Y类点
然后X类点与S点建边,Y类点与T点建边,权值均为这个格子自己的权值
最后在每对相邻的格子间建一条权值为INF的边。。
求最小割时,INF边必然不是割边。
任何一个X类点,若它与S点所连的边不是割边,则所有与它相连的Y类点与T点所连的边必然是割边,否则显然存在增广路。
所以答案就是所有格子权值总和-最小割。
#include<stdio.h> #include<string.h> #define INF 0x7f7f7f7f int p[11000],d[11000],cur[11000],gap[11000],a[110][110],head[11000],sum; int dx[4]={-1,1,0,0},dy[4]={0,0,1,-1},Q[11000]; int E; typedef struct { int u,v,weigh,next; }EDGE; EDGE edge[110000]; void addedge(int u,int v,int weigh) { edge[E].v=v; edge[E].u=u; edge[E].weigh=weigh; edge[E].next=head[u]; head[u]=E++; edge[E].v=u; edge[E].u=v; edge[E].weigh=0; edge[E].next=head[v]; head[v]=E++; } int sap(int n) { int v,u,i,a,mind,ans; for(u=1;u<=n;u++) { cur[u]=head[u]; d[u]=gap[u]=0; } gap[0]=n; u=1;ans=0; memset(p,-1,sizeof(p)); while(d[1]<n) { for(i=cur[u];i!=-1;i=edge[i].next) if(edge[i].weigh&&(d[u]==d[edge[i].v]+1)) break; if(i!=-1) { cur[u]=i; int v=edge[i].v; p[v]=i; u=v; if(v==n) { int a=INF; for(;i!=-1;i=p[edge[i].u])a=a<edge[i].weigh?a:edge[i].weigh; for(v=n;v!=1;v=edge[p[v]].u) { edge[p[v]].weigh-=a; edge[p[v]^1].weigh+=a; } ans+=a; u=1; } } else { int mind=n; for(i=head[u];i!=-1;i=edge[i].next) if(edge[i].weigh)if(mind>d[edge[i].v]+1){mind=d[edge[i].v]+1;cur[u]=i;} --gap[d[u]]; if(gap[d[u]]==0)return ans; ++gap[mind]; d[u]= mind; if(u!=1) u=edge[p[u]].u; } } return ans; } int main() { int n,m,i,j,k,nx,ny; while(scanf("%d%d",&n,&m)==2) { E=0;sum=0; memset(head,-1,sizeof(head)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) { scanf("%d",&a[i][j]); sum+=a[i][j]; if((i^j)&1)addedge((i-1)*m+j+1,n*m+2,a[i][j]); else addedge(1,(i-1)*m+j+1,a[i][j]); } for(i=1;i<=n;i++) for(j=1;j<=m;j++) { if((i^j)&1)continue; for(k=0;k<4;k++) { nx=i+dx[k];ny=j+dy[k]; if(nx&&nx<=n&&ny&&ny<=m) addedge((i-1)*m+j+1,(nx-1)*m+ny+1,INF); } } printf("%d\n",sum-sap(n*m+2)); } }