zoukankan      html  css  js  c++  java
  • 【CODEVS】1033 蚯蚓的游戏问题

    【算法】网络流-最小费用最大流(费用流)

    【题解】与方格取数2类似

    在S后添加辅助点S_,限流k

    每条边不能重复走,限流1

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int inf=0x3f3f3f3f,maxn=40,maxN=5000;
    struct edge{int from,v,flow,cost;}e[150000];
    int n,m,k,tot=1,first[maxN],p[maxn][maxn*2],q[1010],d[maxN],N,S,T,S_;//梯形输入,p的第二维翻倍 
    long long ans;
    bool vis[maxN];
    void insert(int u,int v,int flow,int cost)
    {
        tot++;e[tot].v=v;e[tot].flow=flow;e[tot].cost=cost;e[tot].from=first[u];first[u]=tot;
        tot++;e[tot].v=u;e[tot].flow=0;e[tot].cost=-cost;e[tot].from=first[v];first[v]=tot;
    }
    bool spfa()
    {
        memset(d,0x3f,(N+N+3)*4);
        memset(vis,0,N+N+3);
        int head=0,tail=1;q[0]=T;
        vis[T]=1;d[T]=0;
        while(head!=tail)
         {
             int x=q[head++];if(head>=1001)head=0;
             for(int i=first[x];i;i=e[i].from)
              if(e[i^1].flow&&e[i^1].cost+d[x]<d[e[i].v])
               {
                   d[e[i].v]=d[x]+e[i^1].cost;
                   if(!vis[e[i].v])
                    {
                        vis[e[i].v]=1;q[tail++]=e[i].v;
                        if(tail>=1001)tail=0;
                    }
               }
             vis[x]=0;
         }
        return d[S]<inf;
    }
    int dfs(int x,int a)
    {
        vis[x]=1;
        if(x==T||a==0)return a;
        int flow=0,f;
        for(int i=first[x];i;i=e[i].from)
         if(!vis[e[i].v]&&d[e[i].v]+e[i].cost==d[x]&&(f=dfs(e[i].v,min(a,e[i].flow)))>0)//记得判vis 
          {
              e[i].flow-=f;//正边-,反向弧+ 
              e[i^1].flow+=f;
              ans+=e[i].cost*f;
              a-=f;
              flow+=f;
              if(a==0)break;
          }
        return flow;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        N=0;
        for(int i=1;i<=n;i++)
         {
             for(int j=1;j<=m+i-1;j++)
              {
                  N++;
                  p[i][j]=N;
              }
         }
        S=0,S_=N+N+1,T=N+N+2;//N计算出来后才赋值 
        for(int i=1;i<=n;i++)
         {
             for(int j=1;j<=m+i-1;j++)
              {
                  int x;
                  scanf("%d",&x);
                  insert(p[i][j],p[i][j]+N,1,-x);
                  if(i<n)
                   {
                       insert(p[i][j]+N,p[i+1][j],1,0);
                       insert(p[i][j]+N,p[i+1][j+1],1,0);
                   }
              }
         }
        insert(S,S_,k,0);
        for(int i=1;i<=m;i++)insert(S_,i,1,0);
        for(int i=1;i<=m+n-1;i++)insert(p[n][i]+N,T,1,0);
        ans=0;
        while(spfa())
         {
    //         for(int i=0;i<=N+N+2;i++)printf("[%d]%d
    ",i,d[i]);
             memset(vis,0,N+N+3);
            dfs(S,inf); 
         }
        printf("%lld",-ans);
        return 0;
    }
    View Code
  • 相关阅读:
    算法竞赛入门经典习题2-3 韩信点兵
    ios入门之c语言篇——基本函数——5——素数判断
    ios入门之c语言篇——基本函数——4——数值交换函数
    144. Binary Tree Preorder Traversal
    143. Reorder List
    142. Linked List Cycle II
    139. Word Break
    138. Copy List with Random Pointer
    137. Single Number II
    135. Candy
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6476615.html
Copyright © 2011-2022 走看看