zoukankan      html  css  js  c++  java
  • 洛谷P3356 火星探险问题(费用流)

    传送门

    深海机器人问题差不多……看到有的大佬是用dp过的,强无敌……

    考虑一下,把每一个点拆点,分别是$A_i$和$B_i$,连一条容量为$inf$,费用为$0$的边,表示可以随便走。如果有石头,再连一条边,容量为$1$,费用为$1$,表示只能走一次,且有$1$的价值。然后套路的建一个超级源和超级汇之后跑一个最大费用流即可

    至于如何输出方案,可以一遍$dfs$,每一次只选一条边,然后判断一下这条边被选的次数是否大于等于反向边的流量,如果是说明已经不能再选,然后去选别的边

      1 //minamoto
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<queue>
      6 #define inf 0x3f3f3f3f
      7 using namespace std;
      8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
      9 char buf[1<<21],*p1=buf,*p2=buf;
     10 inline int read(){
     11     #define num ch-'0'
     12     char ch;bool flag=0;int res;
     13     while(!isdigit(ch=getc()))
     14     (ch=='-')&&(flag=true);
     15     for(res=num;isdigit(ch=getc());res=res*10+num);
     16     (flag)&&(res=-res);
     17     #undef num
     18     return res;
     19 }
     20 char sr[1<<21],z[20];int C=-1,Z;
     21 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
     22 inline void print(int x){
     23     if(C>1<<20)Ot();
     24     while(z[++Z]=x%10+48,x/=10);
     25     while(sr[++C]=z[Z],--Z);
     26 }
     27 const int N=5005,M=50005;
     28 int ver[M],Next[M],head[N],edge[M],flow[M],tmp[M],tot=1;
     29 int dis[N],disf[N],Pre[N],last[N],vis[N],maxflow=0;
     30 int ans[N],m=0;
     31 int id[55][55],mp[55][55];
     32 int n,p,q,s,t,num=0;
     33 queue<int> Q;
     34 inline void add(int u,int v,int f,int e){
     35     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,flow[tot]=f,edge[tot]=e;
     36     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,flow[tot]=0,edge[tot]=-e;
     37 }
     38 bool spfa(){
     39     memset(dis,0xef,sizeof(dis));
     40     Q.push(s),dis[s]=0,disf[s]=inf,Pre[t]=-1;
     41     while(!Q.empty()){
     42         int u=Q.front();Q.pop();vis[u]=0;
     43         for(int i=head[u];i;i=Next[i]){
     44             int v=ver[i];
     45             if(flow[i]&&dis[v]<dis[u]+edge[i]){
     46                 dis[v]=dis[u]+edge[i],last[v]=i,Pre[v]=u;
     47                 disf[v]=min(disf[u],flow[i]);
     48                 if(!vis[v]) vis[v]=1,Q.push(v);
     49             }
     50         }
     51     }
     52     return ~Pre[t];
     53 }
     54 void dinic(){
     55     while(spfa()){
     56         int u=t;maxflow+=disf[t];
     57         while(u!=s){
     58             flow[last[u]]-=disf[t];
     59             flow[last[u]^1]+=disf[t];
     60             u=Pre[u];
     61         }
     62     }
     63 }
     64 void dfs(int x,int y){
     65     int now=id[x][y],d0=id[x+1][y],d1=id[x][y+1];
     66     for(int i=head[now+num];i;i=Next[i]){
     67         if(tmp[i]>=flow[i^1]) continue;
     68         if(ver[i]==d0){
     69             ++tmp[i],ans[++m]=0;
     70             dfs(x+1,y);
     71             return;
     72         }
     73         if(ver[i]==d1){
     74             ++tmp[i],ans[++m]=1;
     75             dfs(x,y+1);
     76             return;
     77         }
     78     }
     79 }
     80 int main(){
     81     n=read(),q=read(),p=read();
     82     for(int i=1;i<=p;++i)
     83     for(int j=1;j<=q;++j)
     84     id[i][j]=++num;
     85     s=0,t=num*2+1;
     86     for(int i=1;i<=p;++i)
     87     for(int j=1;j<=q;++j)
     88     mp[i][j]=read();
     89     add(s,id[1][1],n,0),add(id[p][q],t,n,0);
     90     for(int i=1;i<=p;++i)
     91     for(int j=1;j<=q;++j){
     92         if(mp[i][j]&1) continue;
     93         add(id[i][j],id[i][j]+num,inf,0);
     94         if(mp[i][j]) add(id[i][j],id[i][j]+num,1,1);
     95     }
     96     for(int i=1;i<=p;++i)
     97     for(int j=1;j<=q;++j){
     98         if(mp[i][j]&1) continue;
     99         if(i<p&&mp[i+1][j]!=1) add(id[i][j]+num,id[i+1][j],inf,0);
    100         if(j<q&&mp[i][j+1]!=1) add(id[i][j]+num,id[i][j+1],inf,0);
    101     }
    102     dinic();
    103     for(int i=1;i<=maxflow;++i){
    104         m=0,dfs(1,1);
    105         for(int j=1;j<=m;++j) print(i),sr[++C]=' ',print(ans[j]),sr[++C]='
    ';
    106     }
    107     Ot();
    108     return 0;
    109 }
  • 相关阅读:
    在ASP.Net中两种利用CSS实现多界面的方法
    c# 添加图片水印,可以指定水印位置+生成缩略图[付上帅图1,2,3,4]
    精力有限,本博客暂停维护,转到www.80back.com(个人的小站)
    设计一个silverlight的Button控件silverlight(银光)学习(1)
    asp.net(c#)上传图片生成缩略图
    DataGrid和存储过程结合的分页,只读取当前页数据
    c#实现google样式的分页
    asp.net MD5加密函数(c#)
    执行JS
    LoadRunner常见问题
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9507805.html
Copyright © 2011-2022 走看看