zoukankan      html  css  js  c++  java
  • POJ 3422 K取方格数(费用流)/TYVJ 1413

    昨天刚学网络流,于是拿这道题练手。

    这道题最关键的就是建边,首先,对于这个题,限制流量是重点,我这里就提供限制流量的方法:拆点!

    (我作图水平极差,大家凑合着看吧!)

    我们把每个格子拆成两个点,这连个点之间连一条容量为1,权值为map[i][j]的边

    再连一条容量为INF,权值为0的边

    这样就限制了流量,也就是取这个格子最多只能取一次,至于以后再经过这个格子,只能通过第二条容量为INF的边,这样就取不到这个格子的数了

    为了叙述方便我们设每个格子的第一个点为1,第二个点为2

    对于一个格子的2号点,连边如上图。

    从2号点连出来的边意味着通过这个格子以后可以向下边的格子和左边的格子走

    最后对于左上角和右下角的点分别和超级源点S,和超级汇点T连一条容量为k,权为0的边(表示最多只能走k次,即k取方格数)

    ps:以上边都是有向边,抱歉,由于害怕图太乱,就没有连,大家理解思想就行了!

    这样图就建完了,然后就是模板化的跑最大费用流就好了!

    改良版:

    View Code
      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <iostream>
      5 #define N 5500
      6 #define M 105000
      7 #define INF 10000000
      8 using namespace std;
      9 int to[M],next[M],len[M],w[M],from[M],head[N],pre[N],n,m,k,S,T,dis[N],q[M<<4],cnt,map[120][25],minlen[N];
     10 bool vis[N];
     11 void read()
     12 {
     13     scanf("%d%d%d",&k,&m,&n);
     14     for(int i=1;i<=n;i++)
     15         for(int j=1;j<=m;j++)
     16             scanf("%d",&map[i][j]);
     17 }
     18 int getnum(int x,int y)
     19 {
     20     return ((x-1)*m+y);
     21 }
     22 inline void add(int u,int v,int p,int wp)
     23 {
     24     from[cnt]=u; to[cnt]=v; w[cnt]=wp; len[cnt]=p; next[cnt]=head[u]; head[u]=cnt++;
     25     from[cnt]=v; to[cnt]=u; w[cnt]=-wp; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
     26 }
     27 void create()
     28 {
     29     memset(head,-1,sizeof head);
     30     cnt=0;
     31     for(int i=1,a,b,c;i<=n-1;i++)
     32         for(int j=1;j<=m-1;j++)
     33         {
     34             a=getnum(i,j); b=getnum(i,j+1); c=getnum(i+1,j);
     35             add(a<<1,a<<1|1,1,map[i][j]);  add(a<<1,a<<1|1,INF,0);
     36             add(a<<1|1,b<<1,INF,0); add(a<<1|1,c<<1,INF,0);
     37         }
     38     for(int j=1,a,b;j<=m-1;j++)
     39     {
     40         a=getnum(n,j); b=getnum(n,j+1);
     41         add(a<<1,a<<1|1,1,map[n][j]);  add(a<<1,a<<1|1,INF,0);
     42         add(a<<1|1,b<<1,INF,0);
     43     }
     44     for(int i=1,a,c;i<=n-1;i++)
     45     {
     46         a=getnum(i,m); c=getnum(i+1,m);
     47         add(a<<1,a<<1|1,1,map[i][m]); add(a<<1,a<<1|1,INF,0);
     48         add(a<<1|1,c<<1,INF,0);
     49     }
     50     int a=getnum(n,m);
     51     add(a<<1,a<<1|1,1,map[n][m]);  add(a<<1,a<<1|1,INF,0);
     52     S=0; T=n*m*2+7;
     53     add(S,getnum(1,1)<<1,k,0);  
     54     add(getnum(n,m)<<1|1,T,k,0);
     55 }
     56 bool spfa()
     57 {
     58     minlen[S]=INF;
     59     for(int i=0;i<=T;i++) dis[i]=-INF;
     60     memset(pre,-1,sizeof pre);
     61     int h=1,t=2,sta;
     62     q[1]=S; vis[S]=true; dis[S]=0;
     63     while(h<t)
     64     {
     65         sta=q[h++];
     66         vis[sta]=false;
     67         for(int i=head[sta];~i;i=next[i])
     68             if(len[i]>0&&dis[to[i]]<dis[sta]+w[i])
     69             {
     70                 dis[to[i]]=dis[sta]+w[i];
     71                 minlen[to[i]]=min(minlen[sta],len[i]);
     72                 pre[to[i]]=i;
     73                 if(!vis[to[i]])
     74                 {
     75                     vis[to[i]]=true;
     76                     q[t++]=to[i];
     77                 }
     78             }
     79     }
     80     if(pre[T]==-1) return false;
     81     else return true;
     82 }
     83 void dec()
     84 {
     85     int tmp=pre[T];
     86     while(tmp!=-1)
     87     {
     88         len[tmp]-=minlen[T];
     89         len[tmp^1]+=minlen[T];
     90         tmp=pre[from[tmp]];
     91     }
     92 }
     93 int max_fee()
     94 {
     95     int ans=0;
     96     while(spfa())
     97     {
     98         ans+=dis[T];
     99         dec();
    100     }
    101     return ans;
    102 }
    103 int main()
    104 {
    105     read();
    106     create();
    107     printf("%d\n",max_fee());
    108     system("pause");
    109     return 0;
    110 }
    111     

    乱连边版:

    View Code
      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <iostream>
      5 #define N 5500
      6 #define M 105000
      7 #define INF 10000000
      8 using namespace std;
      9 int to[M],next[M],len[M],w[M],from[M],head[N],pre[N],n,m,k,S,T,dis[N],q[M<<4],cnt,map[120][25],minlen[N];
     10 bool vis[N];
     11 void read()
     12 {
     13     scanf("%d%d%d",&k,&m,&n);
     14     for(int i=1;i<=n;i++)
     15         for(int j=1;j<=m;j++)
     16             scanf("%d",&map[i][j]);
     17 }
     18 int getnum(int x,int y)
     19 {
     20     return ((x-1)*m+y);
     21 }
     22 inline void add(int u,int v,int p,int wp)
     23 {
     24     from[cnt]=u; to[cnt]=v; w[cnt]=wp; len[cnt]=p; next[cnt]=head[u]; head[u]=cnt++;
     25     from[cnt]=v; to[cnt]=u; w[cnt]=-wp; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
     26 }
     27 void create()
     28 {
     29     memset(head,-1,sizeof head);
     30     cnt=0;
     31     for(int i=1,a,b,c;i<=n-1;i++)
     32         for(int j=1;j<=m-1;j++)
     33         {
     34             a=getnum(i,j); b=getnum(i,j+1); c=getnum(i+1,j);
     35             add(a<<1,a<<1|1,1,map[i][j]);
     36             add(a<<1,b<<1,INF,0);  add(a<<1,b<<1|1,INF,0);  add(a<<1|1,b<<1,INF,0);  add(a<<1|1,b<<1|1,INF,0);
     37             add(a<<1,c<<1,INF,0);  add(a<<1,c<<1|1,INF,0);  add(a<<1|1,c<<1,INF,0);  add(a<<1|1,c<<1|1,INF,0);
     38         }
     39     for(int j=1,a,b;j<=m-1;j++)
     40     {
     41         a=getnum(n,j); b=getnum(n,j+1);
     42         add(a<<1,a<<1|1,1,map[n][j]);
     43         add(a<<1,b<<1,INF,0);  add(a<<1,b<<1|1,INF,0);  add(a<<1|1,b<<1,INF,0);  add(a<<1|1,b<<1|1,INF,0);
     44     }
     45     for(int i=1,a,c;i<=n-1;i++)
     46     {
     47         a=getnum(i,m); c=getnum(i+1,m);
     48         add(a<<1,a<<1|1,1,map[i][m]);
     49         add(a<<1,c<<1,INF,0);  add(a<<1,c<<1|1,INF,0);  add(a<<1|1,c<<1,INF,0);  add(a<<1|1,c<<1|1,INF,0);
     50     }
     51     int a=getnum(n,m);
     52     add(a<<1,a<<1|1,1,map[n][m]);
     53     S=0; T=n*m*2+7;
     54     add(S,getnum(1,1)<<1,k,0);  
     55     add(getnum(n,m)<<1|1,T,k,0);
     56 }
     57 bool spfa()
     58 {
     59     minlen[S]=INF;
     60     for(int i=0;i<=T;i++) dis[i]=-INF;
     61     memset(pre,-1,sizeof pre);
     62     int h=1,t=2,sta;
     63     q[1]=S; vis[S]=true; dis[S]=0;
     64     while(h<t)
     65     {
     66         sta=q[h++];
     67         vis[sta]=false;
     68         for(int i=head[sta];~i;i=next[i])
     69             if(len[i]>0&&dis[to[i]]<dis[sta]+w[i])
     70             {
     71                 dis[to[i]]=dis[sta]+w[i];
     72                 minlen[to[i]]=min(minlen[sta],len[i]);
     73                 pre[to[i]]=i;
     74                 if(!vis[to[i]])
     75                 {
     76                     vis[to[i]]=true;
     77                     q[t++]=to[i];
     78                 }
     79             }
     80     }
     81     if(pre[T]==-1) return false;
     82     else return true;
     83 }
     84 void dec()
     85 {
     86     int tmp=pre[T];
     87     while(tmp!=-1)
     88     {
     89         len[tmp]-=minlen[T];
     90         len[tmp^1]+=minlen[T];
     91         tmp=pre[from[tmp]];
     92     }
     93 }
     94 int max_fee()
     95 {
     96     int ans=0;
     97     while(spfa())
     98     {
     99         ans+=dis[T];
    100         dec();
    101     }
    102     return ans;
    103 }
    104 int main()
    105 {
    106     read();
    107     create();
    108     printf("%d\n",max_fee());
    109     system("pause");
    110     return 0;
    111 }
    112     
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    UVALive 5983 MAGRID DP
    2015暑假训练(UVALive 5983
    poj 1426 Find The Multiple (BFS)
    poj 3126 Prime Path (BFS)
    poj 2251 Dungeon Master 3维bfs(水水)
    poj 3278 catch that cow BFS(基础水)
    poj3083 Children of the Candy Corn BFS&&DFS
    BZOJ1878: [SDOI2009]HH的项链 (离线查询+树状数组)
    洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)
    洛谷P3065 [USACO12DEC]第一!First!(Trie树+拓扑排序)
  • 原文地址:https://www.cnblogs.com/proverbs/p/2659164.html
Copyright © 2011-2022 走看看