【LOJ6225&网络流24题】火星探险问题(费用流)

题意:

 

 

 思路:

【问题分析】

最大费用最大流问题。

【建模方法】

把网格中每个位置拆分成网络中两个节点<i.a>,<i.b>,建立附加源S汇T。

1、对于每个顶点i,j为i东边或南边相邻的一个节点,连接节点<i.b>与节点<j.a>一条容量为无穷大,费用为0的有向边。

2、从每个石块顶点<i.a>到<i.b>连接一条容量为1,费用为1的有向边。

3、从每个非障碍顶点<i.a>到<i.b>连接一条容量为无穷大,费用为0的有向边。

4、从S到登陆舱位置<(1,1),a>连接一条容量为探测车数,费用为0的有向边。

5、从传送器位置<(P,Q),a>到T连接一条容量为探测车数,费用为0的有向边。

求最大费用最大流,最大费用流值就是最多的岩石标本的数量。所有满流边构成多条满流路径,每条从S到T的路径就是一个探测车的路径。

【建模分析】

这个问题可以看做是出发点和目的地唯一的网络运输问题。每个石块点的价值只能计算一次,所以容量限制要设为1,“多个探测车可以在同一时间占据同一位置”,非障碍点内部要有一条容量为无穷大的

边。直接求费用流即可。

输出方案不能直接记增广路上的点,要重新dfs一遍

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef long double ld;
  7 typedef pair<int,int> PII;
  8 typedef pair<ll,ll> Pll;
  9 typedef vector<int> VI;
 10 typedef vector<PII> VII;
 11 typedef pair<ll,ll>P;
 12 #define N  500000
 13 #define M  1000000
 14 #define INF 1e9
 15 #define fi first
 16 #define se second
 17 #define MP make_pair
 18 #define pb push_back
 19 #define pi acos(-1)
 20 #define mem(a,b) memset(a,b,sizeof(a))
 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 23 #define lowbit(x) x&(-x)
 24 #define Rand (rand()*(1<<16)+rand())
 25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 26 #define ls p<<1
 27 #define rs p<<1|1
 28 
 29 const ll MOD=1e9+7,inv2=(MOD+1)/2;
 30       double eps=1e-6;
 31       int dx[4]={-1,1,0,0};
 32       int dy[4]={0,0,-1,1};
 33 
 34 struct node
 35 {
 36     int x,y;
 37 }p[N];
 38 
 39 VI c;
 40 
 41 int head[N],vet[N],nxt[N],len1[N],len2[N],dis[N],inq[N],q[N],pre[N][2],num[50][50][2],a[50][50],f[N],
 42     s,S,T,tot,ans1,ans2,n,m;
 43 
 44 int read()
 45 {
 46    int v=0,f=1;
 47    char c=getchar();
 48    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 49    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 50    return v*f;
 51 }
 52 
 53 void add(int a,int b,int c,int d)
 54 {
 55     nxt[++tot]=head[a];
 56     vet[tot]=b;
 57     len1[tot]=c;
 58     len2[tot]=d;
 59     head[a]=tot;
 60 
 61     nxt[++tot]=head[b];
 62     vet[tot]=a;
 63     len1[tot]=0;
 64     len2[tot]=-d;
 65     head[b]=tot;
 66 }
 67 
 68 int spfa()
 69 {
 70     rep(i,1,s)
 71     {
 72         dis[i]=-INF;
 73         inq[i]=0;
 74     }
 75     int t=0,w=1;
 76     q[1]=S; dis[S]=0; inq[S]=1;
 77     while(t<w)
 78     {
 79         t++; int u=q[t%(s+5)]; inq[u]=0;
 80         int e=head[u];
 81         while(e)
 82         {
 83             int v=vet[e];
 84             if(len1[e]&&dis[u]+len2[e]>dis[v])
 85             {
 86                 dis[v]=dis[u]+len2[e];
 87                 pre[v][0]=u;
 88                 pre[v][1]=e;
 89                 if(!inq[v])
 90                 {
 91                     w++; q[w%(s+5)]=v; inq[v]=1;
 92                 }
 93             }
 94             e=nxt[e];
 95         }
 96     }
 97     if(dis[T]==-INF) return 0;
 98     return 1;
 99 }
100 
101 void dfs(int x,int y)
102 {
103     int u=num[x][y][1];
104     int e=head[u];
105     while(e)
106     {
107         if(f[e]>=len1[e^1])
108         {
109             e=nxt[e];
110             continue;
111         }
112 
113         int v=vet[e];
114         if(v==num[x+1][y][0])
115         {
116             f[e]++; c.pb(0);
117             dfs(x+1,y);
118             return;
119         }
120          else if(v==num[x][y+1][0])
121          {
122              f[e]++; c.pb(1);
123              dfs(x,y+1);
124              return;
125          }
126         e=nxt[e];
127     }
128 }
129 
130 void mcf()
131 {
132     int k=T,t=INF;
133     while(k!=S)
134     {
135         int e=pre[k][1];
136         t=min(t,len1[e]);
137         k=pre[k][0];
138     }
139     ans1+=t;
140     k=T;
141     while(k!=S)
142     {
143         int e=pre[k][1];
144         len1[e]-=t;
145         len1[e^1]+=t;
146         ans2+=t*len2[e];
147         k=pre[k][0];
148     }
149 }
150 
151 int main()
152 {
153     //freopen("1.in","r",stdin);
154     //freopen("1.out","w",stdout);
155     int car=read();
156     n=read(),m=read();
157     swap(n,m);
158     rep(i,1,n)
159      rep(j,1,m) a[i][j]=read();
160     s=0;
161     rep(i,1,n)
162      rep(j,1,m)
163       rep(k,0,1)
164       {
165           num[i][j][k]=++s;
166           p[s].x=i; p[s].y=j;
167       }
168 
169     S=++s,T=++s;
170     p[S].x=p[S].y=1;
171     p[T].x=n; p[T].y=m;
172     rep(i,1,s) head[i]=0;
173     tot=1;
174     rep(i,1,n)
175      rep(j,1,m)
176      {
177          if(a[i][j]==1) continue;
178          add(num[i][j][0],num[i][j][1],INF,0);
179          if(a[i][j]==2) add(num[i][j][0],num[i][j][1],1,1);
180      }
181     rep(i,1,n)
182      rep(j,1,m)
183      {
184          if(a[i][j]==1) continue;
185          if(i+1<=n&&a[i+1][j]!=1) add(num[i][j][1],num[i+1][j][0],INF,0);
186          if(j+1<=m&&a[i][j+1]!=1) add(num[i][j][1],num[i][j+1][0],INF,0);
187      }
188     add(S,num[1][1][0],car,0);
189     add(num[n][m][1],T,car,0);
190     ans1=ans2=0;
191     while(spfa()) mcf();
192     rep(i,1,ans1)
193     {
194         c.clear();
195         dfs(1,1);
196         for(int j=0;j<c.size();j++) printf("%d %d\n",i,c[j]);
197     }
198     return 0;
199 
200 }

 

posted on 2019-10-30 21:43  myx12345  阅读(202)  评论(0编辑  收藏  举报

导航