• 「TJOI 2013」循环格


    题目链接

    戳我

    (Solution)

    我们观察发现循环格要满足每个点的入度都为(1)

    证明:

    我们假设每个点的入读不一定为(1),那么必定有一个或多个点的入度为0,那么则不满足循环格的定义,所以假设错误。所以每个点的入度必然为1。

    所以这样我们就可以开始建图了。先进行拆点操作,将每个点拆成(x)(x')(x)(S)连接,流量为(1),费用为(0)再将(x')(T)连接,流量为(1),费用为(0)

    最后对于每个点(x)将它和四周的(')点相连接。流量为1,费用的话在判断一下方向和字符是否相同,如果相同为(0),不同为(1)
    (end.)

    (Code)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int read() {
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9')
            f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9')
            x=x*10+c-'0',c=getchar();
        return x*f;
    }
    struct node {
        int to,next,v,w;
    } a[1000001];
    int dis[10001],f[10001],pre[10001],fa[10001],s,t,n,m,head[10001],cnt,x,y,z,c;
    void add(int x,int y,int c,int v) {
        a[++cnt].to=y;
        a[cnt].next=head[x];
        a[cnt].v=c;
        a[cnt].w=v;
        head[x]=cnt;
    }
    queue < int > q;
    int spfa() {
        q.push(s);
        memset(dis,127,sizeof(dis));
        memset(f,0,sizeof(f));
        f[s]=1,dis[s]=0;
        int inf=dis[s+1];
        while(!q.empty()) {
            int now=q.front();
            q.pop();
            f[now]=0;
            for(int i=head[now]; i; i=a[i].next) {
                int v=a[i].to;
                if(dis[v]>dis[now]+a[i].w&&a[i].v) {
                    dis[v]=dis[now]+a[i].w,pre[v]=i,fa[v]=now;
                    if(!f[v])
                        f[v]=1,q.push(v);
                }
            }
        }
        if(dis[t]!=inf)
            return 1;
        return 0;
    }
    int ans1,ans;
    void anser() {
        while(spfa()) {
            int minx=2147483647;
            for(int i=t; i!=s; i=fa[i])
                minx=min(minx,a[pre[i]].v);
            ans+=minx,ans1+=dis[t]*minx;
            for(int i=t; i!=s; i=fa[i])
                a[pre[i]].v-=minx,(pre[i]%2)?a[pre[i]+1].v+=minx:a[pre[i]-1].v+=minx;
        }
    }
    char hh[10]= {'0','D','U','L','R'};
    int fx[10]= {0,1,-1,0,0};
    int fy[10]= {0,0,0,-1,1};
    char ss[101][101],l[1001];
    int main() {
        int N=read(),M=read();
        s=0,t=N*M*10,n=N*M;
        for(int i=1; i<=n; i++)
            add(s,i,1,0),add(i,s,0,0);
        for(int i=1; i<=n; i++)
            add(i+n,t,1,0),add(t,i+n,0,0);
        for(int i=1; i<=N; i++) {
            cin>>l;
            for(int j=0; j<M; j++)
                ss[i][j+1]=l[j];
        }
        for(int i=1; i<=N; i++)
            for(int j=1; j<=M; j++) {
                char pp=ss[i][j];
                for(int k=1; k<=4; k++) {
                    int X=(i+fx[k]+N-1)%N+1,Y=(j+fy[k]+M-1)%M+1;
                    int now=(i-1)*M+j,nex=(X-1)*M+n+Y,o=(pp==hh[k])^1;
                    add(now,nex,1,o),add(nex,now,0,-o);
                }
            }
        anser();
        printf("%d",ans1);
    }
    
    
  • 相关阅读:
    luarocks argparse
    Shell中for循环的几个常用写法
    linux
    Docker修改镜像源为阿里云
    ntpdate更新服务器时间失败
    linux文本三剑客之 sed
    [Union]C++中Union学习笔记
    [sublime] 利用sublime搭建C/C++编译器
    [wordpress]WordPress地址(URL)错误,修改解决方案
    [wordpress]更新插件时,免去FTP操作
  • 原文地址:https://www.cnblogs.com/hbxblog/p/10262281.html
Copyright © 2020-2023  润新知