HIT2715 Matrix3(最小费用最大流)
题目大概说有一个n×n的矩阵,每个格子都有权值和高度,在这个矩阵中进行最多k次旅行,每次旅行能从当前格子走到相邻且高度更小的格子,走到格子边界就能出去完成这次旅行。每走到一个格子就累加格子的权值然后把该格子的权值设置成0。问能获得的最大权和。
很容易建容量网络。。主要是每个点拆成两个点,中间的边再拆成两条,一条容量1费用-该边权值的边,另一条容量INF费用0的边。。
另外题目要求得是最多k次的旅行,实际上越多显然越好,所以最大流是没问题的。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 #define INF (1<<30) 7 #define MAXN 55*55*2 8 #define MAXM 55*55*2*55*55*4 9 struct Edge{ 10 int u,v,cap,cost,next; 11 }edge[MAXM]; 12 int vs,vt,NV,NE,head[MAXN]; 13 void addEdge(int u,int v,int cap,int cost){ 14 edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost; 15 edge[NE].next=head[u]; head[u]=NE++; 16 edge[NE].u=v; edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost; 17 edge[NE].next=head[v]; head[v]=NE++; 18 } 19 int d[MAXN],pre[MAXN]; 20 bool vis[MAXN]; 21 bool SPFA(){ 22 for(int i=0; i<NV; ++i){ 23 d[i]=INF; vis[i]=0; 24 } 25 d[vs]=0; vis[vs]=1; 26 queue<int> que; 27 que.push(vs); 28 while(!que.empty()){ 29 int u=que.front(); que.pop(); 30 for(int i=head[u]; i!=-1; i=edge[i].next){ 31 int v=edge[i].v; 32 if(edge[i].cap && d[v]>d[u]+edge[i].cost){ 33 d[v]=d[u]+edge[i].cost; 34 pre[v]=i; 35 if(!vis[v]){ 36 vis[v]=1; 37 que.push(v); 38 } 39 } 40 } 41 vis[u]=0; 42 } 43 return d[vt]!=INF; 44 } 45 int MCMF(){ 46 int res=0; 47 while(SPFA()){ 48 int flow=INF,cost=0; 49 for(int u=vt; u!=vs; u=edge[pre[u]].u){ 50 flow=min(flow,edge[pre[u]].cap); 51 } 52 for(int u=vt; u!=vs; u=edge[pre[u]].u){ 53 edge[pre[u]].cap-=flow; 54 edge[pre[u]^1].cap+=flow; 55 cost+=flow*edge[pre[u]].cost; 56 } 57 res+=cost; 58 } 59 return res; 60 } 61 int val[55][55],height[55][55]; 62 int dx[]={0,0,1,-1}; 63 int dy[]={1,-1,0,0}; 64 int main(){ 65 int t,n,k; 66 scanf("%d",&t); 67 while(t--){ 68 scanf("%d%d",&n,&k); 69 for(int i=0; i<n; ++i){ 70 for(int j=0; j<n; ++j) scanf("%d",&val[i][j]); 71 } 72 for(int i=0; i<n; ++i){ 73 for(int j=0; j<n; ++j) scanf("%d",&height[i][j]); 74 } 75 int S=n*n*2; 76 vs=n*n*2+1; vt=vs+1; NV=vt+1; NE=0; 77 memset(head,-1,sizeof(head)); 78 addEdge(vs,S,k,0); 79 for(int i=0; i<n; ++i){ 80 for(int j=0; j<n; ++j){ 81 addEdge(i*n+j,i*n+j+n*n,1,-val[i][j]); 82 addEdge(i*n+j,i*n+j+n*n,INF,0); 83 addEdge(S,i*n+j,INF,0); 84 if(i==0 || j==0 || i==n-1 || j==n-1) addEdge(i*n+j+n*n,vt,INF,0); 85 for(int k=0; k<4; ++k){ 86 int nx=i+dx[k],ny=j+dy[k]; 87 if(nx<0 || nx>=n || ny<0 || ny>=n || height[i][j]<=height[nx][ny]) continue; 88 addEdge(i*n+j+n*n,nx*n+ny,INF,0); 89 } 90 } 91 } 92 printf("%d\n",-MCMF()); 93 } 94 return 0; 95 }