HDU 1565,1569,3657,3280,4307方格取数各种版本

大神 夏天的风 的网络流题集 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

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 3657

 

【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 }
hdu 3820

 

 

 

转载于:https://www.cnblogs.com/wangsouc/articles/3714221.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值