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 }

 

posted @ 2016-04-12 08:53  WABoss  阅读(273)  评论(0编辑  收藏  举报