具体Dinic的思路我不再赘述,主要说一下里面比较神奇的优化。
题目:方格取数2
主要的优化在于(我的初步理解,可能不正确,求指正):当我从某一个点出发没有取得任何流量的时候,这个点可以标记为不可用,用来提高效率。
没加优化之前HDU上的裸最大流都是可以A的,但是方格取数2就T掉(5000ms),加了优化31msA掉。
代码:
#include<iostream> #include<cstring> #include<queue> #include<climits> #include<limits.h> #include<cstdio> using namespace std; const long long INF=0x3f3f3f3f; struct no{ long long next,tar,flow; }edge[1000020]; long long head[10000],k,deep[10000],S,T; void init() { k=0; memset(head,-1,sizeof(head)); } void addEdge(long long s,long long t,long long f) { edge[k].tar=t; edge[k].flow=f; edge[k].next=head[s]; head[s]=k++; } bool buildLevelGraph() { memset(deep,-1,sizeof(deep)); queue<long long> q; q.push(S); deep[S]=0; while(!q.empty()) { long long x; x=q.front(); q.pop(); if(x==T)return true; for(long long i=head[x];i!=-1;i=edge[i].next) { if(deep[edge[i].tar]==-1 && edge[i].flow>0) { deep[edge[i].tar]=deep[x]+1; q.push(edge[i].tar); } } } return false; } long long extend(long long p,long long maxn) { if(p==T)return maxn; long long tflow,pf=0; for(long long i=head[p];i!=-1;i=edge[i].next) { if(edge[i].flow>0 && deep[edge[i].tar]==deep[p]+1) { tflow=extend(edge[i].tar,min(maxn-pf,edge[i].flow)); pf+=tflow; edge[i].flow-=tflow; edge[i^1].flow+=tflow; //if(pf==maxn)return pf; } } if(!pf) { deep[p]=-2;//就是这里,标记点不可用 } return pf; } long long Dinic(long long s,long long t) { long long res=0,fl=0; while(buildLevelGraph()) { res+=extend(s,INF); } return res; } long long m,n,sum; bool legal(int tx,int ty) { if(tx>=1&&tx<=m&&ty>=1&&ty<=n)return true; return false; } int walk[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; int main() { while(~scanf("%d%d",&m,&n)) { init(); T=m*n+1; sum=0; S=0; for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { int t; cin>>t; sum+=t; if((i+j)%2==0) { addEdge(S,(i-1)*n+j,t); addEdge((i-1)*n+j,S,0); for(int z=0;z<4;z++) { int x,y; x=i+walk[z][0]; y=j+walk[z][1]; if(legal(x,y)) { addEdge((i-1)*n+j,(x-1)*n+y,INF); addEdge((x-1)*n+y,(i-1)*n+j,0); } } } else { addEdge((i-1)*n+j,T,t); addEdge(T,(i-1)*n+j,0); for(int z=0;z<4;z++) { int x,y; x=i+walk[z][0]; y=j+walk[z][1]; if(legal(x,y)) { addEdge((x-1)*n+y,(i-1)*n+j,INF); addEdge((i-1)*n+j,(x-1)*n+y,0); } } } } } int maxflow=Dinic(S,T); printf("%d\n",sum-maxflow); } }