Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 304 Accepted Submission(s): 172
还是SAP快:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int VM=101000; const int EM=500100; const int INF=0x3f3f3f3f; struct Edge{ int to,nxt; int cap; }edge[EM<<1]; int n,m,G,S,cnt,head[VM],src,des,map1[110][110],map2[110][110]; int dep[VM],gap[VM],cur[VM],aug[VM],pre[VM]; void addedge(int cu,int cv,int cw){ edge[cnt].to=cv; edge[cnt].cap=cw; edge[cnt].nxt=head[cu]; head[cu]=cnt++; edge[cnt].to=cu; edge[cnt].cap=0; edge[cnt].nxt=head[cv]; head[cv]=cnt++; } int SAP(int n){ int max_flow=0,u=src,v; int id,mindep; aug[src]=INF; pre[src]=-1; memset(dep,0,sizeof(dep)); memset(gap,0,sizeof(gap)); gap[0]=n; for(int i=0;i<=n;i++) cur[i]=head[i]; // 初始化当前弧为第一条弧 while(dep[src]<n){ int flag=0; if(u==des){ max_flow+=aug[des]; for(v=pre[des];v!=-1;v=pre[v]){ // 路径回溯更新残留网络 id=cur[v]; edge[id].cap-=aug[des]; edge[id^1].cap+=aug[des]; aug[v]-=aug[des]; // 修改可增广量,以后会用到 if(edge[id].cap==0) // 不回退到源点,仅回退到容量为0的弧的弧尾 u=v; } } for(int i=cur[u];i!=-1;i=edge[i].nxt){ v=edge[i].to; // 从当前弧开始查找允许弧 if(edge[i].cap>0 && dep[u]==dep[v]+1){ // 找到允许弧 flag=1; pre[v]=u; cur[u]=i; aug[v]=min(aug[u],edge[i].cap); u=v; break; } } if(!flag){ if(--gap[dep[u]]==0) // gap优化,层次树出现断层则结束算法 break; mindep=n; cur[u]=head[u]; for(int i=head[u];i!=-1;i=edge[i].nxt){ v=edge[i].to; if(edge[i].cap>0 && dep[v]<mindep){ mindep=dep[v]; cur[u]=i; // 修改标号的同时修改当前弧 } } dep[u]=mindep+1; gap[dep[u]]++; if(u!=src) // 回溯继续寻找允许弧 u=pre[u]; } } return max_flow; } int main(){ //freopen("input.txt","r",stdin); int t,cases=0; scanf("%d",&t); while(t--){ scanf("%d%d%d%d",&n,&m,&G,&S); cnt=0; memset(head,-1,sizeof(head)); src=0; des=n*m*2+1; int sum=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&map1[i][j]); sum+=map1[i][j]; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&map2[i][j]); sum+=map2[i][j]; } int tmp; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ tmp=(i-1)*m+j; if((i+j)%2==0){ addedge(src,tmp,map1[i][j]); addedge(tmp,tmp+n*m,INF); addedge(tmp+n*m,des,map2[i][j]); if(i>1) addedge(tmp,tmp-m+n*m,G); if(i<n) addedge(tmp,tmp+m+n*m,G); if(j>1) addedge(tmp,tmp-1+n*m,G); if(j<m) addedge(tmp,tmp+1+n*m,G); }else{ addedge(src,tmp,map2[i][j]); addedge(tmp,tmp+n*m,INF); addedge(tmp+n*m,des,map1[i][j]); if(i>1) addedge(tmp,tmp-m+n*m,S); if(i<n) addedge(tmp,tmp+m+n*m,S); if(j>1) addedge(tmp,tmp-1+n*m,S); if(j<m) addedge(tmp,tmp+1+n*m,S); } } } printf("Case %d: %d\n",++cases,sum-SAP(des+1)); } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int VM=101000; const int EM=500100; const int INF=0x3f3f3f3f; struct Edge{ int to,nxt; int cap; }edge[EM<<1]; int n,m,G,S,cnt,head[VM],src,des; int map1[110][110],map2[110][110],dep[VM]; //dep[i]表示当前点到起点src的层数 void addedge(int cu,int cv,int cw){ edge[cnt].to=cv; edge[cnt].cap=cw; edge[cnt].nxt=head[cu]; head[cu]=cnt++; edge[cnt].to=cu; edge[cnt].cap=0; edge[cnt].nxt=head[cv]; head[cv]=cnt++; } int BFS(){ // 重新建图(按层数建图) queue<int> q; while(!q.empty()) q.pop(); memset(dep,-1,sizeof(dep)); dep[src]=0; q.push(src); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(edge[i].cap>0 && dep[v]==-1){ // 如果可以到达且还没有访问 dep[v]=dep[u]+1; q.push(v); } } } return dep[des]!=-1; } int DFS(int u,int minx){ // 查找路径上的最小的流量 if(u==des) return minx; int tmp; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(edge[i].cap>0 && dep[v]==dep[u]+1 && (tmp=DFS(v,min(minx,edge[i].cap)))){ edge[i].cap-=tmp; //正向减少 edge[i^1].cap+=tmp; //反向增加 return tmp; } } dep[u]=-1; //这一句作用无穷大,不在TLE。。。。。。。。。。。 return 0; } int Dinic(){ int ans=0,tmp; while(BFS()){ while(1){ tmp=DFS(src,INF); if(tmp==0) break; ans+=tmp; } } return ans; } int main(){ //freopen("input.txt","r",stdin); int t,cases=0; scanf("%d",&t); while(t--){ scanf("%d%d%d%d",&n,&m,&G,&S); cnt=0; memset(head,-1,sizeof(head)); src=0; des=n*m*2+1; int sum=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&map1[i][j]); sum+=map1[i][j]; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&map2[i][j]); sum+=map2[i][j]; } int tmp; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ tmp=(i-1)*m+j; if((i+j)%2==0){ addedge(src,tmp,map1[i][j]); addedge(tmp,tmp+n*m,INF); addedge(tmp+n*m,des,map2[i][j]); // if(i!=1)addedge(tmp,tmp-m+n*m,G); if(i!=n)addedge(tmp,tmp+m+n*m,G); if(j!=1)addedge(tmp,tmp-1+n*m,G); if(j!=m)addedge(tmp,tmp+1+n*m,G); // } else{ addedge(src,tmp,map2[i][j]); addedge(tmp,tmp+n*m,INF); addedge(tmp+n*m,des,map1[i][j]); if(i!=1)addedge(tmp,tmp-m+n*m,S); if(i!=n)addedge(tmp,tmp+m+n*m,S); if(j!=1)addedge(tmp,tmp-1+n*m,S); if(j!=m)addedge(tmp,tmp+1+n*m,S); } } } printf("Case %d: %d\n",++cases,sum-Dinic()); } return 0; }