HDU 1569 方格取数(2) dinic算法
http://acm.hdu.edu.cn/showproblem.php?pid=1569
题意:
给出M*N的格子,每个格子里都有数字,问你怎么样取数字能使其和最大,前提是取出来的格子不能两两相邻。
坑爹:
如果按照方格取数的方法教上去会超时。
解法:
struct Edge //记录边
{
int from; //边的起点
int to; //边的终点
int cap; //边的容量
int next; //优化DFS和BFS的搜索,因为边有很多个,每次从0开始找的话会超时,所以用个cur数组来初始化。
};
用dinic算法,里面有两个部分比较重要,一个是BFS,另一个是DFS。
BFS:利用BFS来对图进行一个分层,如图所示。
DFS:每次对已经BFS的图进行深搜,条件是每次搜索的下一个结点必须是下一层的结点。记录下这条路径的
最小流量,回溯的时候改变cap的值。
然后就是每次调用BFS看下能不能找到汇点,如果不能的话就结束,能找到的话就DFS计算出当前这个层次图的最大流量,
然后再BFS循环做上述操作。

1 #include<iostream> 2 #include<queue> 3 using namespace std; 4 5 const int maxn = 50+10; 6 const int E_maxn = 50000 + 10; 7 const int INF = 0x3fffffff; 8 9 struct Edge 10 { 11 int from; 12 int to; 13 int cap; 14 int next; 15 }; 16 struct Edge edge[E_maxn]; 17 int deep[maxn*maxn]; 18 int cur[maxn*maxn]; 19 int k; 20 int n; 21 int m; 22 int temp[4][2] = {-1,0, 1,0, 0,-1, 0,1}; 23 24 int MIN(int a,int b) 25 { 26 return a > b ? b : a; 27 } 28 29 void addedge(int from,int to,int cap) 30 { 31 edge[k].from = from; 32 edge[k].to = to; 33 edge[k].cap = cap; 34 edge[k].next = cur[from]; 35 cur[from] = k; 36 k++; 37 edge[k].from = to; 38 edge[k].to = from; 39 edge[k].cap = 0; 40 edge[k].next = cur[to]; 41 cur[to] = k; 42 k++; 43 } 44 45 int judge(int x,int y) 46 { 47 if(x>0 && x<=n && y>0 && y<=m) 48 { 49 return 1; 50 } 51 return 0; 52 } 53 54 bool BFS() 55 { 56 memset(deep,-1,sizeof(deep)); 57 queue<int> Q; 58 Q.push(0); 59 deep[0] = 0; 60 while(!Q.empty()) 61 { 62 int x = Q.front(); 63 Q.pop(); 64 int i; 65 for(i=cur[x]; i!=-1; i=edge[i].next) 66 { 67 int e = edge[i].to; 68 if(deep[e] == -1 && edge[i].cap > 0) 69 { 70 deep[e] = deep[x] + 1; 71 Q.push(e); 72 } 73 } 74 } 75 return deep[n*m+1] != -1; 76 } 77 78 int DFS(int x,int a) 79 { 80 if(x == n*m+1) 81 { 82 return a; 83 } 84 int flow = 0; 85 for(int i=cur[x]; i!=-1 && flow<a; i=edge[i].next) 86 { 87 int e = edge[i].to; 88 if(deep[x] + 1 == deep[e] && edge[i].cap > 0) 89 { 90 int f = MIN(edge[i].cap,a-flow); 91 f = DFS(e,f); 92 flow += f; 93 edge[i].cap -= f; 94 edge[i^1].cap += f; 95 } 96 } 97 if(!flow) 98 { 99 deep[x] = -2;//没有必要再往这个点走了 100 } 101 return flow; 102 } 103 104 int Dinic() 105 { 106 int flow = 0; 107 int F=0; 108 while(BFS()) 109 { 110 while(F=DFS(0,INF)) 111 { 112 flow += F; 113 } 114 } 115 return flow; 116 } 117 118 119 int main() 120 { 121 while(cin>>n>>m) 122 { 123 int i; 124 int j; 125 memset(cur,-1,sizeof(cur)); 126 k=0; 127 int sum = 0; 128 int num; 129 for(i=1; i<=n; i++) 130 { 131 for(j=1; j<=m; j++) 132 { 133 scanf("%d",&num); 134 sum+=num; 135 if((i+j) % 2 == 0) 136 { 137 addedge(0,(i-1)*m+j,num); 138 for(int z = 0; z<4; z++) 139 { 140 int x = i+temp[z][0]; 141 int y = j+temp[z][1]; 142 if(judge(x,y)) 143 { 144 addedge((i-1)*m+j,(x-1)*m+y,INF); 145 } 146 } 147 } 148 else 149 { 150 addedge((i-1)*m+j,n*m+1,num); 151 for(int z = 0; z<4; z++) 152 { 153 int x = i+temp[z][0]; 154 int y = j+temp[z][1]; 155 if(judge(x,y)) 156 { 157 addedge((x-1)*m+y,(i-1)*m+j,INF); 158 } 159 } 160 } 161 } 162 } 163 164 int ans = Dinic(); 165 cout<<sum-ans<<endl; 166 } 167 return 0; 168 }