zoukankan      html  css  js  c++  java
  • 洛咕 P3965 [TJOI2013]循环格

    同tjoi2010 打扫房间,每个点入度,出度都为1,可以向相邻4个点连边,但只有原来存在的边费用为0。

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    typedef long long ll;
    il int gi(){
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    char s[20][20];
    const int maxn=500,maxm=100000;
    int S,T,n,m,fir[maxn],dis[maxm],nxt[maxm],w[maxm],cost[maxm],id=1;
    il vd link(int a,int b,int c,int d){
        nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c,cost[id]=d;
        nxt[++id]=fir[b],fir[b]=id,dis[id]=a,w[id]=0,cost[id]=-d;
    }
    const int X[]={0,1,-1,0,0},Y[]={0,0,0,1,-1};
    const char form[]="0DURL";
    int num[16][16][2];
    il bool Mincost(int&total){
        static int que[maxn],hd,tl,dist[maxn],lst[maxn];
        static bool inq[maxn];
        hd=tl=0;que[tl++]=S;inq[S]=1;
        memset(dist,63,sizeof dist);dist[S]=0;
        memset(lst,0,sizeof lst);
        while(hd^tl){
            int x=que[hd];
            for(int i=fir[x];i;i=nxt[i])
                if(w[i]&&dist[dis[i]]>dist[x]+cost[i]){
                    dist[dis[i]]=dist[x]+cost[i],lst[dis[i]]=i;
                    if(!inq[dis[i]])inq[dis[i]]=1,que[tl++]=dis[i],tl%=maxn;
                }
            ++hd;hd%=maxn;inq[x]=0;
        }
        for(int i=lst[T];i;i=lst[dis[i^1]])--w[i],++w[i^1],total+=cost[i];
        return lst[T];
    }
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("3965.in","r",stdin);
        freopen("3965.out","w",stdout);
    #endif
        n=gi(),m=gi();
        for(int i=1;i<=n;++i)scanf("%s",s[i]+1);
        int cnt=0;S=++cnt,T=++cnt;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j){
                num[i][j][0]=++cnt,link(S,num[i][j][0],1,0);
                num[i][j][1]=++cnt,link(num[i][j][1],T,1,0);
            }
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                for(int k=1;k<=4;++k){
                    int xx=i+X[k],yy=j+Y[k];
                    if(xx>n)xx=1;if(yy>m)yy=1;
                    if(xx==0)xx=n;if(yy==0)yy=m;
                    link(num[i][j][0],num[xx][yy][1],1,s[i][j]!=form[k]);
                }
        int ans=0;while(Mincost(ans));printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    中断向量表
    内核进程的堆栈 [转]
    int指令理解
    Linux进程创建和结束
    Linux 信号signal处理机制
    wait和waitpid详解
    linux 如何清理僵尸进程
    API:System V & POSI
    shell
    Code POJ
  • 原文地址:https://www.cnblogs.com/xzz_233/p/9826506.html
Copyright © 2011-2022 走看看