大神 夏天的风 的网络流题集 http://blog.csdn.net/shahdza/article/details/7779537
hdu 1565\1569属于比较简单的方格取数,二分图中:最大点权独立集 = 点权数 - 最大流(最小割)。另外1565也可以状态压缩DP做。
hdu 3657\4307 同属于公式化解类型
【hdu 3657 题意】N*M的方格里,每个数字aij,可以选出若干数字,最终得分为所选数字之后 - 选择了相邻数字的2*(X & Y),相邻只两个方格有相同边。
【分析】
hdu 3657 SAP版本 46MS
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #include<vector> 6 7 using namespace std; 8 9 const int maxn = 2511; 10 const int maxm = 20010; 11 const int inf = 1000000000 ; 12 13 const int INF = 10000000; 14 15 16 17 struct SAP{ 18 struct Edge{ 19 int v, next; 20 int w; 21 }edge[maxm]; 22 int head[maxn]; 23 24 int cnt; 25 int n, s, t;//n = t + 1; 26 27 28 int pre[maxn],cur[maxn],dis[maxn],gap[maxn]; 29 30 void add(int u,int v,int w, int k) 31 { 32 edge[cnt].v=v; 33 edge[cnt].w=w; 34 edge[cnt].next=head[u]; 35 head[u]=cnt++; 36 edge[cnt].v=u; 37 edge[cnt].w=0; 38 edge[cnt].next=head[v]; 39 head[v]=cnt++; 40 } 41 42 int sap() 43 { 44 int flow=0,aug=inf; 45 int u; 46 bool flag; 47 for(int i=0;i<=n;i++) 48 { 49 cur[i]=head[i]; 50 gap[i]=dis[i]=0; 51 } 52 gap[s]=n; 53 u=pre[s]=s; 54 while(dis[s]<n) 55 { 56 flag=0; 57 for(int &j=cur[u];j!=-1;j=edge[j].next) 58 { 59 int v=edge[j].v; 60 if(edge[j].w>0&&dis[u]==dis[v]+1) 61 { 62 flag=1; 63 if(edge[j].w<aug) aug=edge[j].w; 64 pre[v]=u; 65 u=v; 66 if(u==t) 67 { 68 flow+=aug; 69 while(u!=s) 70 { 71 u=pre[u]; 72 edge[cur[u]].w-=aug; 73 edge[cur[u]^1].w+=aug; 74 } 75 aug=inf; 76 } 77 break; 78 } 79 } 80 if(flag) 81 continue; 82 int mindis=n; 83 for(int j=head[u];j!=-1;j=edge[j].next) 84 { 85 int v=edge[j].v; 86 if(edge[j].w>0&&dis[v]<mindis) 87 { 88 mindis=dis[v]; 89 cur[u]=j; 90 } 91 } 92 if((--gap[dis[u]])==0) 93 break; 94 gap[dis[u]=mindis+1]++; 95 u=pre[u]; 96 } 97 98 return flow; 99 100 } 101 102 void init(int __n,int __s, int __t) 103 { 104 n = __n; 105 s = __s; 106 t = __t; 107 cnt = 0; 108 memset(head,-1,sizeof(head)); 109 } 110 }Flow; 111 112 int n, m , k; 113 int a[51][51]; 114 bool vis[51][51]; 115 116 int main() 117 { 118 while (scanf("%d%d%d",&n,&m,&k)==3) 119 { 120 int nn = n*m + 2, s = 0, t = n*m + 1; 121 int res = 0; 122 Flow.init(nn,s,t); 123 124 for (int i=1;i<=n;i++) 125 { 126 for (int j=1;j<=m;j++) 127 { 128 scanf("%d",&a[i][j]); 129 res += a[i][j]; 130 } 131 } 132 memset(vis, 0, sizeof(vis)); 133 while (k--) 134 { 135 int x, y; 136 scanf("%d%d",&x,&y); 137 vis[x][y] = 1; 138 } 139 for (int i=1;i<=n;i++) 140 { 141 for (int j =1;j<=m;j++) 142 { 143 int p = i * m + j - m; 144 if ((i+j)%2 == 0){ 145 if (vis[i][j]) 146 Flow.add(s, p, INF, 0); 147 148 Flow.add(s, p, a[i][j],0); 149 if (i < n) 150 { 151 Flow.add(p, p+m, 2*(a[i][j] & a[i+1][j]), 0); 152 } 153 if (i > 1){ 154 Flow.add(p, p - m , 2*(a[i][j] & a[i-1][j]), 0); 155 } 156 if (j < m) 157 { 158 Flow.add(p, p + 1 , 2*(a[i][j] & a[i][j+1]), 0); 159 } 160 if (j > 1) 161 { 162 Flow.add(p, p - 1 , 2*(a[i][j] & a[i][j-1]), 0); 163 } 164 }else{ 165 if (vis[i][j]) 166 Flow.add(p, t, INF, 0); 167 Flow.add(p, t, a[i][j],0); 168 169 } 170 } 171 } 172 res -= Flow.sap(); 173 174 printf("%d\n",res); 175 } 176 return 0; 177 }
hdu 3657 Dinic版本 62MS
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #include<vector> 6 7 using namespace std; 8 9 const int maxn = 25011; 10 const int maxm = 35010; 11 const int inf = 100000000; 12 13 14 15 16 struct Dinic{ 17 int node, src, dest, ne; 18 int head[maxn], work[maxn], dist[maxn],Q[maxn]; 19 int flow[maxm], pnt[maxm], nxt[maxm]; 20 void init(int _node, int _src, int _dest) 21 { 22 node = _node; 23 src = _src; 24 dest = _dest; 25 for (int i=0;i<node;i++) 26 { 27 head[i] = -1; 28 } 29 ne = 0; 30 } 31 void add(int u,int v, int c1,int c2) 32 { 33 pnt[ne] = v, flow[ne] = c1, nxt[ne] = head[u], head[u] = ne++; 34 pnt[ne] = u, flow[ne] = c2, nxt[ne] = head[v], head[v] = ne++; 35 36 } 37 bool dinic_bfs(void) 38 { 39 int i,u,v,l,r=0; 40 for(int i=0;i<node;i++) dist[i]=-1; 41 dist[Q[r++]=src]=0; 42 for(l=0;l<r;l++) for(i=head[u=Q[l]];i>=0;i=nxt[i]) 43 if(flow[i] && dist[v=pnt[i]]<0) 44 { 45 dist[Q[r++]=v]=dist[u]+1; 46 if(v==dest) return 1; 47 } 48 return 0; 49 } 50 int dinic_dfs(int u,int exp) 51 { 52 if(u==dest) return exp; 53 for(int &i=work[u],v,tmp;i>=0;i=nxt[i]) 54 if(flow[i] && dist[v=pnt[i]]==dist[u]+1 && (tmp=dinic_dfs(v,min(exp,flow[i])))>0) 55 { 56 flow[i]-=tmp; 57 flow[i^1]+=tmp; 58 return tmp; 59 } 60 return 0; 61 } 62 int dinic_flow(void) 63 { 64 int i,res=0,delta; 65 while(dinic_bfs()) 66 { 67 for(i=0;i<node;i++) work[i]=head[i]; 68 while(delta=dinic_dfs(src,inf)) res+=delta; 69 } 70 return res; 71 } 72 }Flow; 73 74 int n, m , k; 75 int a[51][51]; 76 bool vis[51][51]; 77 78 int main() 79 { 80 while (scanf("%d%d%d",&n,&m,&k)==3) 81 { 82 int nn = n*m + 2, s = 0, t = n*m + 1; 83 int res = 0; 84 Flow.init(nn,s,t); 85 86 for (int i=1;i<=n;i++) 87 { 88 for (int j=1;j<=m;j++) 89 { 90 scanf("%d",&a[i][j]); 91 res += a[i][j]; 92 } 93 } 94 memset(vis, 0, sizeof(vis)); 95 while (k--) 96 { 97 int x, y; 98 scanf("%d%d",&x,&y); 99 vis[x][y] = 1; 100 } 101 for (int i=1;i<=n;i++) 102 { 103 for (int j =1;j<=m;j++) 104 { 105 int p = i * m + j - m; 106 if ((i+j)%2 == 0){ 107 if (vis[i][j]) 108 Flow.add(s, p, inf, 0); 109 Flow.add(s, p, a[i][j],0); 110 111 if (i < n) 112 { 113 Flow.add(p, p+m, 2*(a[i][j] & a[i+1][j]), 0); 114 } 115 if (i > 1){ 116 Flow.add(p, p - m , 2*(a[i][j] & a[i-1][j]), 0); 117 } 118 if (j < m) 119 { 120 Flow.add(p, p + 1 , 2*(a[i][j] & a[i][j+1]), 0); 121 } 122 if (j > 1) 123 { 124 Flow.add(p, p - 1 , 2*(a[i][j] & a[i][j-1]), 0); 125 } 126 }else{ 127 if (vis[i][j]) 128 Flow.add(p, t, inf, 0); 129 Flow.add(p, t, a[i][j],0); 130 131 132 } 133 } 134 } 135 res -= Flow.dinic_flow(); 136 137 printf("%d\n",res); 138 } 139 return 0; 140 }
【hdu 3820 题意】N*M的方格里,可以放金蛋,价值+aij;银蛋,价值+bij;相邻两个如果是金蛋-G, 如果是银蛋-S;
【分析】此前各种方格取数的加强版。
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #include<vector> 6 7 using namespace std; 8 9 const int maxn = 5511; 10 const int maxm = 40010; 11 const int inf = 1000000000 ; 12 13 const int INF = 10000000; 14 15 struct SAP{ 16 struct Edge{ 17 int v, next; 18 int w; 19 }edge[maxm]; 20 int head[maxn]; 21 22 int cnt; 23 int n, s, t;//n = t + 1; 24 25 26 int pre[maxn],cur[maxn],dis[maxn],gap[maxn]; 27 28 void add(int u,int v,int w) 29 { 30 edge[cnt].v=v; 31 edge[cnt].w=w; 32 edge[cnt].next=head[u]; 33 head[u]=cnt++; 34 edge[cnt].v=u; 35 edge[cnt].w=0; 36 edge[cnt].next=head[v]; 37 head[v]=cnt++; 38 } 39 40 int sap() 41 { 42 int flow=0,aug=inf; 43 int u; 44 bool flag; 45 for(int i=0;i<=n;i++) 46 { 47 cur[i]=head[i]; 48 gap[i]=dis[i]=0; 49 } 50 gap[s]=n; 51 u=pre[s]=s; 52 while(dis[s]<n) 53 { 54 flag=0; 55 for(int &j=cur[u];j!=-1;j=edge[j].next) 56 { 57 int v=edge[j].v; 58 if(edge[j].w>0&&dis[u]==dis[v]+1) 59 { 60 flag=1; 61 if(edge[j].w<aug) aug=edge[j].w; 62 pre[v]=u; 63 u=v; 64 if(u==t) 65 { 66 flow+=aug; 67 while(u!=s) 68 { 69 u=pre[u]; 70 edge[cur[u]].w-=aug; 71 edge[cur[u]^1].w+=aug; 72 } 73 aug=inf; 74 } 75 break; 76 } 77 } 78 if(flag) 79 continue; 80 int mindis=n; 81 for(int j=head[u];j!=-1;j=edge[j].next) 82 { 83 int v=edge[j].v; 84 if(edge[j].w>0&&dis[v]<mindis) 85 { 86 mindis=dis[v]; 87 cur[u]=j; 88 } 89 } 90 if((--gap[dis[u]])==0) 91 break; 92 gap[dis[u]=mindis+1]++; 93 u=pre[u]; 94 } 95 96 return flow; 97 98 } 99 100 void init(int __n,int __s, int __t) 101 { 102 n = __n; 103 s = __s; 104 t = __t; 105 cnt = 0; 106 memset(head,-1,sizeof(head)); 107 } 108 }Flow; 109 110 int n, m, G, S; 111 int a[51][51]; 112 int b[51][51]; 113 114 int main() 115 { 116 int cas, cast = 0; 117 scanf("%d",&cas); 118 while (cas--){ 119 scanf("%d%d",&n,&m); 120 scanf("%d%d",&G,&S); 121 int ans = 0; 122 for (int i=1;i<=n;i++) 123 for (int j=1;j<=m;j++){ 124 scanf("%d",&a[i][j]); 125 ans += a[i][j]; 126 } 127 for (int i=1;i<=n;i++) 128 for (int j=1;j<=m;j++) 129 { 130 scanf("%d",&b[i][j]); 131 ans += b[i][j]; 132 } 133 134 int nn = 2*n*m + 2; 135 int s = 0, t = nn - 1; 136 137 Flow.init(nn,s,t); 138 for (int i=1;i<=n;i++) 139 { 140 for (int j=1;j<=m;j++) 141 { 142 int p = i*m - m + j; 143 int pp = p + n*m; 144 Flow.add(p, pp, INF); 145 146 if ((i + j)%2 == 0){ 147 Flow.add(s, p, a[i][j]); 148 Flow.add(pp, t, b[i][j]); 149 150 if (i < n) 151 { 152 int q = p + m; 153 int qq = q + n*m; 154 Flow.add(p, qq, G); 155 Flow.add(q, pp, S); 156 } 157 if (i > 1) 158 { 159 int q = p - m; 160 int qq = q + n*m; 161 Flow.add(p, qq, G); 162 Flow.add(q, pp, S); 163 } 164 if (j < m) 165 { 166 int q = p + 1; 167 int qq = q + n*m; 168 Flow.add(p, qq, G); 169 Flow.add(q, pp, S); 170 171 } 172 if (j > 1) 173 { 174 int q = p - 1; 175 int qq = q + n*m; 176 Flow.add(p, qq, G); 177 Flow.add(q, pp, S); 178 } 179 }else{ 180 Flow.add(s, p, b[i][j]); 181 Flow.add(pp, t, a[i][j]); 182 } 183 } 184 } 185 186 ans = ans - Flow.sap(); 187 printf("Case %d: %d\n",++cast, ans); 188 } 189 return 0; 190 }