• [CQOI2017]老C的方块


    题目描述

    https://www.lydsy.com/JudgeOnline/problem.php?id=4823

    题解

    观察那四种条件

    有没有什么特点?

    我们可以把蓝线两边的部分看做两个区域,这样的话任何一个不合法的匹配都是在蓝线两边都必须有格子,而且那两个格子的临近位置也需要有一个格子。

    如果我们把蓝线两边的格子看做一个点,那不就是我们所熟悉的三元匹配模型了吗?

    如果我们建出了图,求一下最小割就好了。

    关键是这个图怎么建。

    除了蓝线两边的以外的点黑白染色,匹配顺序为白->紫->紫->黑,就可以建出图来了。

    代码

    #include<iostream>
    #include<cstdio>
    #include<map>
    #include<cstring>
    #include<queue>
    #define N 100002
    #define inf 2e9
    using namespace std;
    queue<int>q;
    int tot=1,head[N],deep[N],cur[N],C,R,n;
    map<int,int>mp[N];
    map<int,int>::iterator it;
    long long ans;
    inline int rd(){
        int x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    struct edge{
        int n,to,l;
    }e[N*6];
    inline void add(int u,int v,int l){
        e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;
        e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=0;
    }
    inline bool bfs(int s,int t){
        memset(deep,0,sizeof(deep));
        memcpy(cur,head,sizeof(head));
        deep[s]=1;q.push(s);
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].n){
                int v=e[i].to;
                if(!deep[v]&&e[i].l){
                    deep[v]=deep[u]+1;q.push(v);
                }
            }
        }
        return deep[t];
    }
    int dfs(int u,int t,int l){
        if(u==t||!l)return l;
        int f,flow=0;
        for(int &i=cur[u];i;i=e[i].n){
            int v=e[i].to;
            if(deep[v]==deep[u]+1&&(f=dfs(v,t,min(l,e[i].l)))){
                e[i].l-=f;e[i^1].l+=f;flow+=f;l-=f;
                if(!l)break;
            }
        }
        return flow;
    }
    struct block{
        int u,v,w;
    }a[N];
    int main(){
        C=rd();R=rd();n=rd();
        for(int i=1;i<=n;++i){
            a[i].u=rd();a[i].v=rd();a[i].w=rd();
            swap(a[i].u,a[i].v);
            mp[a[i].u][a[i].v]=i;
        }
        for(int i=1;i<=n;++i){
            if(a[i].u&1){
              if(a[i].v%4==1){
                it=mp[a[i].u].find(a[i].v+1);
                if(it!=mp[a[i].u].end()){
                    int x=it->second;
                    add(i,x,min(a[i].w,a[x].w));
                }
              }
              else if(a[i].v%4==2||a[i].v%4==0){
                  if(a[i].v%4==0)add(0,i,a[i].w);
                  it=mp[a[i].u].find(a[i].v+1);
                  if(it!=mp[a[i].u].end()){
                          int x=it->second;
                          add(i,x,inf);
                }
                it=mp[a[i].u+1].find(a[i].v);
                if(it!=mp[a[i].u+1].end()){
                          int x=it->second;
                          add(i,x,inf);
                }
                it=mp[a[i].u-1].find(a[i].v);
                if(it!=mp[a[i].u-1].end()){
                          int x=it->second;
                          add(i,x,inf);
                }
              }
              else if(a[i].v%4==3){
                  add(i,n+1,a[i].w);
              }
            }
            else{
                if(a[i].v%4==1||a[i].v%4==3){
                if(a[i].v%4==1)add(0,i,a[i].w);
                it=mp[a[i].u].find(a[i].v-1);
                  if(it!=mp[a[i].u].end()){
                          int x=it->second;
                          add(i,x,inf);
                }
                it=mp[a[i].u+1].find(a[i].v);
                if(it!=mp[a[i].u+1].end()){
                          int x=it->second;
                          add(i,x,inf);
                }
                it=mp[a[i].u-1].find(a[i].v);
                if(it!=mp[a[i].u-1].end()){
                          int x=it->second;
                          add(i,x,inf);
                }
                } 
                else if(a[i].v%4==0){
                    it=mp[a[i].u].find(a[i].v-1);
                   if(it!=mp[a[i].u].end()){
                    int x=it->second;
                    add(i,x,min(a[i].w,a[x].w));
                   }
                }
                else add(i,n+1,a[i].w);
            }
        }
        while(bfs(0,n+1))ans+=dfs(0,n+1,2e9);
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    tableau prep 转置-pivot
    tabeau 画Slopegraph斜面图
    java栈
    java快速排序
    java冒泡排序
    java实现双向链表
    五、使用依赖注入取代硬连接资源(静态工厂、单例),也可用于构造方法、bulider模式
    转 String的不变性 immutable
    三、使用私有构造方法(公开成员属性或者公开静态工厂方法)或者枚举类实现singleton
    有状态对象和无状态对象
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10275114.html
Copyright © 2020-2023  润新知