网络流24题之火星探险问题

最大费用最大流

向他能走的方向连边,如果有石头可以选则连一条流量为1费用为1的边

dfs输出结果即可。

By:大奕哥

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=50,M=2500,inf=1e9;
  4 int n,p,q,ff,s,t,l,cnt=-1,tot;
  5 bool v[M];
  6 int from[M],turn[M],head[M],d[M],m[N][N],pos[N][N],tmp[M];
  7 struct node{
  8     int to,nex,w,from,c;
  9 }e[200005];
 10 void add(int x,int y,int w,int c)
 11 {
 12     e[++cnt].to=y;e[cnt].from=x;e[cnt].c=c;e[cnt].nex=head[x];head[x]=cnt;e[cnt].w=w;
 13     e[++cnt].to=x;e[cnt].from=y;e[cnt].c=-c;e[cnt].nex=head[y];head[y]=cnt;e[cnt].w=0;
 14 }
 15 queue<int>qq;
 16 bool spfa()
 17 {
 18     memset(d,-0x3f,sizeof(d));
 19     memset(v,0,sizeof(v));
 20     d[s]=0;v[s]=1;qq.push(s);
 21     memset(from,-1,sizeof(from));
 22     while(!qq.empty())
 23     {
 24         int x=qq.front();qq.pop();
 25         for(int i=head[x];i!=-1;i=e[i].nex)
 26         {
 27             int y=e[i].to;
 28             if(d[y]>=d[x]+e[i].c||!e[i].w)continue;
 29             d[y]=d[x]+e[i].c;from[y]=i;
 30             if(!v[y])qq.push(y),v[y]=1;
 31         }
 32         v[x]=0;
 33     }
 34     int flow=1e9;
 35     for(int i=from[t];i!=-1;i=from[e[i].from])
 36     flow=min(flow,e[i].w);
 37     if(flow!=1e9)
 38     for(int i=from[t];i!=-1;i=from[e[i].from])
 39     e[i].w-=flow,e[i^1].w+=flow;
 40     if(d[t]<0)return 0;
 41     return 1;
 42 }
 43 void dinic()
 44 {
 45     while(spfa());
 46 }
 47 void dfs(int x,int y)
 48 {
 49     if(x==p&&y==q)return;
 50     int rx=pos[x][y+1],dx=pos[x+1][y],xx=pos[x][y]+tot;
 51     for(int i=head[xx];i!=-1;i=e[i].nex)
 52     {
 53         int yy=e[i].to;
 54         if(tmp[i]>=e[i^1].w)continue;
 55         if(yy==rx)
 56         {
 57             ++tmp[i];
 58             turn[++l]=1;
 59             dfs(x,y+1);
 60             return;
 61         }
 62         if(yy==dx)
 63         {
 64             ++tmp[i];
 65             turn[++l]=0;
 66             dfs(x+1,y);
 67             return;
 68         }
 69     }
 70     return;
 71 }
 72 int main()
 73 {
 74     scanf("%d%d%d",&n,&q,&p);
 75     memset(head,-1,sizeof(head));
 76     for(int i=1;i<=p;++i)
 77     for(int j=1;j<=q;++j)
 78     {
 79         scanf("%d",&m[i][j]);
 80         pos[i][j]=++tot;
 81     }
 82     s=0;t=tot*2+1;
 83     for(int i=1;i<=p;++i)
 84     for(int j=1;j<=q;++j)
 85     {
 86         if(m[i][j]==1)continue;
 87         add(pos[i][j],pos[i][j]+tot,inf,0);
 88         if(m[i][j])
 89         add(pos[i][j],pos[i][j]+tot,1,1);
 90         if(i+1<=p)
 91         add(pos[i][j]+tot,pos[i+1][j],inf,0);
 92         if(j+1<=q)
 93         add(pos[i][j]+tot,pos[i][j+1],inf,0);
 94     }
 95     add(s,1,n,0);add(tot*2,t,n,0);
 96     dinic();
 97     for(int i=1;i<=n;++i)
 98     {
 99         l=0;dfs(1,1);
100         for(int j=1;j<=l;++j)printf("%d %d\n",i,turn[j]);
101     }
102     return 0;
103 }

 

posted @ 2018-02-01 10:42  大奕哥&VANE  阅读(150)  评论(0编辑  收藏  举报