标签:time \n turn scanf mil main i++ man out
描述
给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
输入
包括多个测试实例,每个测试实例包括2整数m,n和m行n列的非负数(m<=50,n<=50)
输出
对于每个测试实例,输出可能取得的最大的和
样例输入
3 3
75 15 21
75 15 28
34 70 5
样例输出
188
题意
如上
题解
最大点权独立集=总权值-最小点权覆盖
用最小割跑出来的是最小点权覆盖,再用sum-最小点权覆盖
把图黑白染色,黑色点连源点S流量a[i][j],白色点连汇点T流量a[i][j],然后每个相邻的黑白点连黑白边流量INF,跑最小割即可
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=1e5+5; 5 const int maxm=2e5+5; 6 int n,m,S,T; 7 int deep[maxn],q[400000]; 8 int FIR[maxn],TO[maxm],CAP[maxm],COST[maxm],NEXT[maxm],tote; 9 10 void add(int u,int v,int cap) 11 { 12 TO[tote]=v; 13 CAP[tote]=cap; 14 NEXT[tote]=FIR[u]; 15 FIR[u]=tote++; 16 17 TO[tote]=u; 18 CAP[tote]=0; 19 NEXT[tote]=FIR[v]; 20 FIR[v]=tote++; 21 } 22 bool bfs() 23 { 24 memset(deep,0,sizeof deep); 25 deep[S]=1;q[1]=S; 26 int head=0,tail=1; 27 while(head!=tail) 28 { 29 int u=q[++head]; 30 for(int v=FIR[u];v!=-1;v=NEXT[v]) 31 { 32 if(CAP[v]&&!deep[TO[v]]) 33 { 34 deep[TO[v]]=deep[u]+1; 35 q[++tail]=TO[v]; 36 } 37 } 38 } 39 return deep[T]; 40 } 41 int dfs(int u,int fl) 42 { 43 if(u==T)return fl; 44 int f=0; 45 for(int v=FIR[u];v!=-1&&fl;v=NEXT[v]) 46 { 47 if(CAP[v]&&deep[TO[v]]==deep[u]+1) 48 { 49 int Min=dfs(TO[v],min(fl,CAP[v])); 50 CAP[v]-=Min;CAP[v^1]+=Min; 51 fl-=Min;f+=Min; 52 } 53 } 54 if(!f)deep[u]=-2; 55 return f; 56 } 57 int maxflow() 58 { 59 int ans=0; 60 while(bfs()) 61 ans+=dfs(S,1<<28); 62 return ans; 63 } 64 void init() 65 { 66 tote=0; 67 memset(FIR,-1,sizeof FIR); 68 } 69 int N,M,a[55][55],color[55][55],has[55][55],tot,sum,f; 70 int main() 71 { 72 while(cin>>N>>M) 73 { 74 init(); 75 memset(color,0,sizeof color); 76 tot=sum=0; 77 for(int i=1;i<=N;i++) 78 { 79 if(i&1)f=1; 80 else f=-1; 81 for(int j=1;j<=M;f*=-1,j++) 82 { 83 scanf("%d",&a[i][j]); 84 sum+=a[i][j]; 85 has[i][j]=tot++; 86 color[i][j]=f; 87 } 88 } 89 S=tot,T=S+1; 90 for(int i=1;i<=N;i++) 91 for(int j=1;j<=M;j++) 92 { 93 if(color[i][j]==1) 94 add(S,has[i][j],a[i][j]); 95 else 96 add(has[i][j],T,a[i][j]); 97 if(color[i-1][j]==-1)add(has[i][j],has[i-1][j],1<<28); 98 if(color[i+1][j]==-1)add(has[i][j],has[i+1][j],1<<28); 99 if(color[i][j-1]==-1)add(has[i][j],has[i][j-1],1<<28); 100 if(color[i][j+1]==-1)add(has[i][j],has[i][j+1],1<<28); 101 } 102 cout<<sum-maxflow()<<‘\n‘; 103 } 104 return 0; 105 }
标签:time \n turn scanf mil main i++ man out
原文地址:https://www.cnblogs.com/taozi1115402474/p/9535779.html