zoukankan      html  css  js  c++  java
  • [BZOJ 2668] 交换棋子

    Link:

    BZOJ 2668 传送门

    Solution:

    重点在于对于每条转移路径:首尾算一次,中间节点算两次

    可以一点拆三点,将原流量拆成入流量和出流量

    但其实也可以就拆两点,分前后是否是一首尾点一普通点来确定是否有一条路径只占用1流量

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=1e5+10,INF=1<<30;
    int n,m,cnt1,cnt2;char dat[2][30][30],lmt[30][30];
    
    namespace mcmf
    {
        struct edge
        {int to,cap,cost,rev;};
        vector<edge> a[MAXN];
        int S,T,h[MAXN],dist[MAXN],preV[MAXN],preE[MAXN],maxf,minc;
        
        void add_edge(int from,int to,int cap,int cost)
        {
            a[from].push_back(edge{to,cap,cost,a[to].size()});
            a[to].push_back(edge{from,0,-cost,a[from].size()-1});
        }
        void min_cost_flow(int f)
        {
            while(f>0)
            {
                priority_queue<P,vector<P>,greater<P> > que;
                fill(dist,dist+T+1,INF);
                dist[S]=0;que.push(P(0,S));
                while(!que.empty())
                {
                    P t=que.top();que.pop();
                    int v=t.Y;if(dist[v]<t.X) continue;
                    
                    for(int i=0;i<a[v].size();i++)
                    {
                        edge &e=a[v][i];
                        if(e.cap>0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to])
                            dist[e.to]=dist[v]+e.cost+h[v]-h[e.to],
                            preV[e.to]=v,preE[e.to]=i,que.push(P(dist[e.to],e.to));
                    }
                }
                if(dist[T]==INF) break;
                for(int i=1;i<=T;i++) h[i]+=dist[i];
                
                int d=f;
                for(int i=T;i!=S;i=preV[i])
                    d=min(d,a[preV[i]][preE[i]].cap);
                f-=d;minc+=d*h[T];maxf+=d;
                for(int i=T;i!=S;i=preV[i])
                {
                    edge &e=a[preV[i]][preE[i]];
                    e.cap-=d,a[i][e.rev].cap+=d;
                }
            }
        }
    }
    using namespace mcmf;
    int dx[]={1,1,1,-1,-1,-1,0,0};
    int dy[]={1,-1,0,1,-1,0,1,-1};
    int idx(int x,int y,int z){return (x-1)*m+y+n*m*z;}
    
    int main()
    {
        scanf("%d%d",&n,&m);
        S=0;T=2*n*m+1;
        for(int i=1;i<=n;i++) scanf("%s",dat[0][i]+1);
        for(int i=1;i<=n;i++) scanf("%s",dat[1][i]+1);
        for(int i=1;i<=n;i++) scanf("%s",lmt[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(dat[0][i][j]=='1')
                    cnt1++,add_edge(S,idx(i,j,0),1,0);
                if(dat[1][i][j]=='1')
                    cnt2++,add_edge(idx(i,j,1),T,1,0);
                if(dat[0][i][j]==dat[1][i][j])
                    add_edge(idx(i,j,0),idx(i,j,1),(lmt[i][j]-'0')/2+dat[0][i][j]-'0',0);
                else add_edge(idx(i,j,0),idx(i,j,1),(lmt[i][j]-'0'+1)/2,0);
                
                for(int k=0;k<8;k++)
                {
                    int fx=i+dx[k],fy=j+dy[k];
                    if(fx<1||fx>n||fy<1||fy>m) continue;
                    add_edge(idx(i,j,1),idx(fx,fy,0),INF,1);
                }
            }
        
        min_cost_flow(INF);
        if(cnt1!=cnt2||maxf!=cnt1) puts("-1");
        else printf("%d",minc);
        return 0;
    }
  • 相关阅读:
    ORA-12170 TNS 连接超时
    判断字符串里面是否包含汉字
    关于Try/Catch 代码块
    SOLID 原则
    整洁代码原则
    装箱 拆箱
    存储过程优缺点
    ANTLR Tool version 4.4中使用ANTLR 4.7.1
    The Apache Tomcat installation at this directory is version 8.5.40. A Tomcat 8.0 installation is expected.
    实现功能:构建一个JSON到XML的翻译器。
  • 原文地址:https://www.cnblogs.com/newera/p/9583960.html
Copyright © 2011-2022 走看看