D - 文理分科 (网络流->最小割)
题目链接:https://cn.vjudge.net/contest/281959#problem/D
题目大意:中文题目
具体思路:我们需要求出最大的满意值,从另一方面想,我们可以求出总的满意值,然后再求出不符合情况的最小的代价,这两个相减,就能求出最大的满意值,这个时候就可以通过最小割来求了(最小割:使得整个图不连通的最小花费)。
这一篇博客讲的很好:https://blog.csdn.net/yakeding/article/details/79357545
AC代码:
1 #include<iostream> 2 #include<stack> 3 #include<queue> 4 #include<iomanip> 5 #include<stdio.h> 6 #include<cstring> 7 #include<cstring> 8 #include<cmath> 9 #include<algorithm> 10 #include<map> 11 #include<vector> 12 using namespace std; 13 # define ll long long 14 # define maxn 6000000+100 15 # define inf 0x3f3f3f3f 16 int prev[maxn];//边的编号 17 int head[maxn]; 18 int f[2][4]= {{1,-1,0,0},{0,0,1,-1}}; 19 struct node 20 { 21 int to; 22 int flow; 23 int nex; 24 } edge[maxn]; 25 int num,st,ed; 26 void init() 27 { 28 memset(head,-1,sizeof(head)); 29 num=0; 30 } 31 void addedge(int fr,int to,int flow) 32 { 33 edge[num].to=to; 34 edge[num].flow=flow; 35 edge[num].nex=head[fr]; 36 head[fr]=num++; 37 edge[num].to=fr; 38 edge[num].flow=0; 39 edge[num].nex=head[to]; 40 head[to]=num++; 41 } 42 bool bfs() 43 { 44 memset(prev,-1,sizeof(prev)); 45 prev[st]=1; 46 queue<int>q; 47 q.push(st); 48 while(!q.empty()) 49 { 50 int top=q.front(); 51 q.pop(); 52 for(int i=head[top]; i!=-1; i=edge[i].nex) 53 { 54 int temp=edge[i].to; 55 if(prev[temp]==-1&&edge[i].flow>0) 56 { 57 prev[temp]=prev[top]+1; 58 q.push(temp); 59 } 60 } 61 } 62 return prev[ed]!=-1; 63 } 64 int dfs(int u,int flow) 65 { 66 if(u==ed) 67 return flow; 68 int res=0; 69 for(int i=head[u]; i!=-1; i=edge[i].nex) 70 { 71 int t=edge[i].to; 72 if(prev[t]==(prev[u]+1)&&edge[i].flow>0) 73 { 74 int temp=dfs(t,min(flow,edge[i].flow)); 75 edge[i].flow-=temp; 76 edge[i^1].flow+=temp; 77 res+=temp; 78 flow-=temp; 79 if(flow==0) 80 break; 81 } 82 } 83 if(res==0) 84 prev[u]=-1; 85 return res; 86 } 87 int n,m; 88 int dinic() 89 { 90 int ans=0; 91 while(bfs()) 92 { 93 ans+=dfs(st,inf); 94 } 95 return ans; 96 } 97 bool judge(int t1,int t2) 98 { 99 if(t1>=1&&t1<=n&&t2>=1&&t2<=m) 100 return true; 101 return false; 102 } 103 int main() 104 { 105 init(); 106 int sum=0; 107 int tmp; 108 st=1e5,ed=1e5+1; 109 scanf("%d %d",&n,&m); 110 for(int i=1; i<=n; i++) 111 { 112 for(int j=1; j<=m; j++) 113 { 114 scanf("%d",&tmp); 115 sum+=tmp; 116 addedge((i-1)*m+j,ed,tmp); 117 } 118 } 119 for(int i=1; i<=n; i++) 120 { 121 for(int j=1; j<=m; j++) 122 { 123 scanf("%d",&tmp); 124 sum+=tmp; 125 addedge(st,(i-1)*m+j,tmp); 126 } 127 } 128 for(int i=1; i<=n; i++) 129 { 130 for(int j=1; j<=m; j++) 131 { 132 scanf("%d",&tmp); 133 addedge((i-1)*m+j,((i-1)*m+j)+n*m,inf); 134 addedge(((i-1)*m+j)+n*m,ed,tmp); 135 sum+=tmp; 136 for(int k=0; k<4; k++) 137 { 138 int x=i+f[0][k]; 139 int y=j+f[1][k]; 140 if(judge(x,y)) 141 addedge((x-1)*m+y,((i-1)*m+j)+n*m,inf); 142 } 143 } 144 } 145 for(int i=1; i<=n; i++) 146 { 147 for(int j=1; j<=m; j++) 148 { 149 scanf("%d",&tmp); 150 sum+=tmp; 151 addedge(((i-1)*m+j)+n*m*2,(i-1)*m+j,inf); 152 addedge(st,((i-1)*m+j)+n*m*2,tmp); 153 for(int k=0; k<4; k++) 154 { 155 int x=i+f[0][k]; 156 int y=j+f[1][k]; 157 if(judge(x,y)) 158 addedge(((i-1)*m+j)+n*m*2,(x-1)*m+y,inf); 159 } 160 } 161 } 162 // cout<<1<<endl; 163 int ans=dinic(); 164 // cout<<1<<endl; 165 printf("%d\n",sum-ans); 166 return 0; 167 }