把題目意思理解清楚以後,就會發現這道題跟POJ 3469 那道雙核處理器是一樣的
公式第一項只要當xi=0時才會有作用,第二項只有當xi=1時才會有作用,第三項只有當xi和xj不相等時才會有作用
對於每個點i,xi要麼等於0,要麼等於1,即點i要麼屬於S集,要麼屬於T集,如果點i,j不在同一個集合,它們之間還會產生附加值
總的最小value值正好對應一個最小割的容量,value=Sum(v0i)+Sum(v1j)+Sum(vij),令v0為源點,v1為匯點,則i表示點i屬於S集,點j表示j屬於T集,當(s,i)為割邊時,(i,t)不會是割邊,同理,(i,t)為割邊時,(s,i)不會是割邊,當i,j在同一個集合時,(i,j)不會是割邊
這題公式第三項1<=i<j<=N,j屬於N(i),但下面說j屬於N(i)表示的是點i的左右和上下鄰點,但由於j>i,只能取右邊鄰點和下邊鄰點(如果存在的話),一開始在這裡WA了幾次
還有就是除了最後一組測試資料,每組結束後都要多打一行空行,一開始只打了一個分行符號,在調試的時候看起來時空了一行,實際是那行本來要輸出結果的,但有由於要先讀資料,把那行空出來了,所以還要多打一個分行符號,囧。。這個PE了兩次
代碼:
#include<iostream><br />#include<stdio.h><br />#include<stdlib.h><br />#include<math.h><br />#include<memory.h><br />using namespace std;<br />const int inf=1<<30;<br />const int MAX=505;<br />struct node<br />{<br />int v,c,next;<br />}g[MAX*MAX*2];<br />int dis[MAX],num[MAX],cur[MAX],pre[MAX],adj[MAX],map[MAX][MAX];<br />int s,t,e,vn;<br />void add(int u,int v,int c)<br />{<br />g[e].v=v; g[e].c=c; g[e].next=adj[u]; adj[u]=e++;<br />g[e].v=u; g[e].c=0; g[e].next=adj[v]; adj[v]=e++;<br />}<br />int ABS(int x)<br />{<br />return x>0?x:-x;<br />}<br />int sap()<br />{<br />int i,u,v,flow=0,aug=inf,flag;<br />for(i=0;i<=vn;i++)<br />{<br />dis[i]=num[i]=0;<br />cur[i]=adj[i];<br />}<br />num[0]=vn;<br />pre[s]=u=s;<br />while(dis[s]<vn)<br />{<br />flag=0;<br />for(i=cur[u];i!=-1;i=g[i].next)<br />{<br />v=g[i].v;<br />if(g[i].c&&dis[u]==dis[v]+1)<br />{<br />flag=1;<br />pre[v]=u;<br />cur[u]=i;<br />aug=aug<g[i].c?aug:g[i].c;<br />u=v;<br />if(u==t)<br />{<br />flow+=aug;<br />while(u!=s)<br />{<br />u=pre[u];<br />g[cur[u]].c-=aug;<br />g[cur[u]^1].c+=aug;<br />}<br />aug=inf;<br />}<br />break;<br />}<br />}<br />if(flag)<br />continue;<br />if(--num[dis[u]]==0)<br />break;<br />for(dis[u]=vn,i=adj[u];i!=-1;i=g[i].next)<br />{<br />v=g[i].v;<br />if(g[i].c&&dis[v]<dis[u])<br />{<br />dis[u]=dis[v];<br />cur[u]=i;<br />}<br />}<br />dis[u]++;<br />num[dis[u]]++;<br />u=pre[u];<br />}<br />return flow;<br />}<br />int main()<br />{<br />int i,j,k,T,ca,v0,v1,r,col;<br />scanf("%d",&T);<br />for(ca=1;ca<=T;ca++)<br />{<br />scanf("%d %d %d %d",&r,&col,&v0,&v1);<br />e=0;<br />memset(adj,-1,sizeof(adj));<br />memset(map,0,sizeof(map));<br />s=0;<br />t=r*col+1;<br />vn=t+1;<br />for(i=1;i<=r;i++)<br />{<br />for(j=1;j<=col;j++)<br />{<br />scanf("%d",&map[i][j]);<br />}<br />}<br />for(i=1;i<=r;i++)<br />{<br />for(j=1;j<=col;j++)<br />{<br />k=(i-1)*col+j;<br />add(s,k,ABS(map[i][j]-v0));<br />add(k,s,ABS(map[i][j]-v0));<br />add(k,t,ABS(map[i][j]-v1));<br />add(t,k,ABS(map[i][j]-v1));<br />/*if(i>1)<br />{<br />add(k,k-col,ABS(map[i][j]-map[i-1][j]));<br />add(k-col,k,ABS(map[i][j]-map[i-1][j]));<br />}*/<br />if(i<r)<br />{<br />add(k,k+col,ABS(map[i][j]-map[i+1][j]));<br />add(k+col,k,ABS(map[i][j]-map[i+1][j]));<br />}<br />/*if(j>1)<br />{<br />add(k,k-1,ABS(map[i][j]-map[i][j-1]));<br />add(k-1,k,ABS(map[i][j]-map[i][j-1]));<br />}*/<br />if(j<col)<br />{<br />add(k,k+1,ABS(map[i][j]-map[i][j+1]));<br />add(k+1,k,ABS(map[i][j]-map[i][j+1]));<br />}<br />}<br />}<br />printf("Case %d:/n",ca);<br />printf("%d/n",sap());<br />if(ca<T)<br />printf("/n");<br />}<br />return 0;<br />}