• 【Luogu】P3356火星探险问题(费用流)


      题目链接

      网络流一条边都不能多连?没道理呀?

      不过单看这题的确是个sb题……

      

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #define maxn 100
    #define maxm 100000
    #define lim n*m
    #define F(i,j) ((i-1)*m+j)
    #define T(i,j) (F(i,j)+lim)
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    struct Edge{
        int from,next,to,val,dis,flow;
    }edge[maxm];
    int head[maxn*maxn],num;
    inline void addedge(int from,int to,int val,int dis){
        edge[++num]=(Edge){from,head[from],to,val,dis,0};
        head[from]=num;
    }
    inline void add(int from,int to,int val,int dis){
        addedge(from,to,val,dis);
        addedge(to,from,0,-dis);
    }
    
    inline int count(int i){    return i&1?i+1:i-1;    }
    
    int dis[maxn*maxn];
    int flow[maxn*maxn];
    int pre[maxn*maxn];
    bool vis[maxn*maxn];
    int Start,End;
    int n,m;
    
    int spfa(){
        memset(dis,-127/3,sizeof(dis));    dis[Start]=0;    flow[Start]=0x7fffffff;
        queue<int>q;    q.push(Start);
        while(!q.empty()){
            int from=q.front();    q.pop();    vis[from]=0;
            for(int i=head[from];i;i=edge[i].next){
                int to=edge[i].to;
                if(edge[i].val<=edge[i].flow||dis[to]>=dis[from]+edge[i].dis)    continue;
                dis[to]=dis[from]+edge[i].dis;
                pre[to]=i;    flow[to]=min(flow[from],edge[i].val-edge[i].flow);
                if(vis[to])    continue;
                vis[to]=1;    q.push(to);
            }
        }
        int now=End;
        while(now!=Start){
            int ret=pre[now];
            edge[ret].flow+=flow[End];
            edge[count(ret)].flow-=flow[End];
            now=edge[ret].from;
        }
        return dis[End];
    }
    
    struct Node{
        int x,y;
    };
    
    Node calc(int ret){
        Node ans;
        ans.x=(ret-1)/m+1;
        ans.y=ret-(ans.x-1)*m;
        return ans;
    }
    
    Node q[maxn*maxn];int tot;
    
    void dfs(int x,int y,int now){
        if(now==End)    return;
        for(int i=head[now];i;i=edge[i].next){
            int to=edge[i].to;
            if(edge[i].flow==0)    continue;
            edge[i].flow--;    edge[i].val--;
            if(to<=lim)    q[++tot]=calc(to);
            dfs(q[tot].x,q[tot].y,to);
            return;
        }
    }
    
    bool ext[maxn][maxn];
    
    int main(){
        int e=read();
        m=read();n=read();
        Start=1;    End=n*m*2;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j){
                int x=read();
                if(i!=1&&ext[i-1][j]==0)    add(T(i-1,j),F(i,j),0x7fffffff,0);
                if(j!=1&&ext[i][j-1]==0)    add(T(i,j-1),F(i,j),0x7fffffff,0);
                if(x==1){
                    ext[i][j]=1;
                    continue;
                }
                add(F(i,j),T(i,j),1,x==2?1:0);
                add(F(i,j),T(i,j),0x7fffffff,0);
                
            }
        int cnt=0;
        while(1){
            int now=spfa();
            if(now<0)    break;
            cnt++;
            if(cnt>e)    break;
            tot=0;
            dfs(1,1,1);
            q[0]=(Node){1,1};
            for(int j=1;j<=tot;++j){
                Node a=q[j-1],b=q[j];
                if(a.x==b.x)    printf("%d %d
    ",cnt,1);
                else            printf("%d %d
    ",cnt,0);
            }
        }
        return 0;
    }
  • 相关阅读:
    抽象工厂
    MVC模型验证+客户端验证
    模型绑定
    Linq 构建块
    Linq的简单应用_01
    简单的Jquery轮播
    实现自己的代码生成器
    JS练习--闭包
    node部署网页
    IE8-浏览器下iframe的动态onload事件处理
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8449320.html
Copyright © 2020-2023  润新知