zoukankan      html  css  js  c++  java
  • 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
    ",-MCMF());
    93     }
    94     return 0;
    95 }
  • 相关阅读:
    Discuz论坛自动发帖机
    C#测试数据库连接是否成功
    JS重写提示框(confirm)
    随笔 选择
    随笔 诚实
    web项目经理手册【1】版本控制流程
    Asp.net多层架构中的变量引用与传递
    ASP.NET跨页面传值技巧总结
    web项目经理手册【3】Code Review
    web项目经理手册【7】项目经理需要铭记在心的话
  • 原文地址:https://www.cnblogs.com/WABoss/p/5381261.html
Copyright © 2011-2022 走看看