• CF1045A Last Chance


    线段树优化建图二分图匹配w!

    输出方案有点烦QAQ

    大体做法:

    1.对于第0种直接连上就可以啦

    2.对于第1种线段树优化建图就好啦 就是建一棵线段树连进来再连出去就吼啦

    3.对于第2种比较复杂 下面详细说一说

    首先我们可以贪心全选第三种 因为它不重复覆盖

    所以我们假定所有的第三种都是选了 a 和 b

    接下来我们处理可以连到c的或者连a/b替换c

    那么我们建图是这样建 当前点连a/b建反向边容量1 然后当前点连向c容量为1大概长这样

    然后如果有流量到A/B我们可以替换掉C 

    最后输出方案 我们用map记录一下每条流量的走向 反向往回退流就可以了

    还有学习到了一点map小知识 比如这样

    map<int,int>::iterator it=mp.begin();
    it->first;
    it->second;

    map是键值对 所以这里的first就是键 second是值

    比如说 mp[x]=y; first是x second就是y

    退流的时候比较方便

    //Love and Freedom.
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<map>
    #define ll long long
    #define inf 20021225
    #define ls (x<<1)
    #define rs (x<<1|1)
    #define fa (x>>1)
    #define mid (l+r>>1)
    #define N 100010 
    using namespace std;
    struct edge{int to,lt,f;}e[N*40];
    int in[N],cnt=1,tot,n,m,ss,tt;
    queue<int> q; int dis[N];
    void add(int x,int y,int f)
    {
        //printf("%d %d %d
    ",x,y,f);
        e[++cnt].to=y; e[cnt].lt=in[x]; e[cnt].f=f; in[x]=cnt;
        e[++cnt].to=x; e[cnt].lt=in[y]; e[cnt].f=0; in[y]=cnt; 
    }
    bool bfs()
    {
        while(!q.empty())    q.pop();
        memset(dis,0,sizeof(dis)); dis[ss]=1; q.push(ss);
        while(!q.empty())
        {
            int x=q.front(); q.pop();// printf("QWQ");
            for(int i=in[x];i;i=e[i].lt)
            {
                int y=e[i].to;
                if(e[i].f && !dis[y])
                {
                    dis[y]=dis[x]+1,q.push(y);
                    if(y==tt)    return 1;
                }
            } 
        }
        return 0;
    }
    int dfs(int x,int flow)
    {
        //if(x==tt)    printf("%d
    ",flow);
        if(!flow || x==tt)    return flow;
        int cur=flow;
        for(int i=in[x];i;i=e[i].lt)
        {
            int y=e[i].to;
            if(dis[y]==dis[x]+1 && e[i].f)
            {
                int tmp=dfs(y,min(e[i].f,cur));
                if(tmp)
                {
                    cur-=tmp; e[i].f-=tmp; e[i^1].f+=tmp;
                    if(!cur)    return flow;
                }
            }
        }
        dis[x]=-1; return flow-cur;
    }
    int id[N];
    void build(int x,int l,int r)
    {
        id[x]=++tot;
        if(l==r){add(id[x],l,1); return;}
        build(ls,l,mid); add(id[x],id[ls],inf);
        build(rs,mid+1,r); add(id[x],id[rs],inf);
    }
    void link(int x,int l,int r,int LL,int RR,int v)
    {
        if(LL<=l && RR>=r){add(v,id[x],1); return;}
        if(LL<=mid)    link(ls,l,mid,LL,RR,v);
        if(RR>mid)    link(rs,mid+1,r,LL,RR,v);
    }
    int dinic()
    {
        int tmp=0;// printf("QWQ");
        while(bfs())    tmp+=dfs(ss,inf);
        return tmp;
    }
    map<int,int>mp[N]; int beg;
    bool vis[N]; int tp;
    void query(int x)
    {
        if(x>beg){tp=x-beg; return;}
        map<int,int>::iterator it=mp[x].begin();
        query(it->first); --it->second;
        if(!it->second) mp[x].erase(it);     
    }
    int main()
    {
        int typ,l,r,x,K,k,a,b,c,ans=0;
        scanf("%d%d",&n,&m);
        tot=m; ss=++tot; build(1,1,m); beg=tot;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&typ); ++tot; 
            if(typ==0)
            {
                scanf("%d",&K);
                while(K--)    scanf("%d",&k),add(tot,k,1);
                add(ss,tot,1);
            }
            else if(typ==1)
            {
                scanf("%d%d",&l,&r);
                link(1,1,m,l,r,tot); add(ss,tot,1);
            }
            else
            {
                scanf("%d%d%d",&a,&b,&c);
                vis[a]=vis[b]=1; ans+=2;
                add(tot,a,0),e[cnt].f=1; add(tot,b,0),e[cnt].f=1; add(tot,c,1);
            }
        }
        tt=++tot;
        for(int i=1;i<=m;i++)    if(!vis[i])    add(i,tt,1);
        ans+=dinic(); printf("%d
    ",ans);
        for(int i=1;i<=tot;i++)    for(int j=in[i];j;j=e[j].lt)
            if((j&1) && e[j].f)    mp[i][e[j].to]=e[j].f;
        for(int i=1;i<=m;i++)
        {
            bool flag=1;
            for(int j=in[i];j&&flag;j=e[j].lt)
                if(e[j].to==tt&&e[j].f)    flag=0;
            if(flag)    query(i),printf("%d %d
    ",tp,i);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    UVA 125 Numbering Paths
    UVA 515 King
    UVA 558 Wormholes
    UVA 10801 Lift Hopping
    UVA 10896 Sending Email
    SGU 488 Dales and Hills
    HDU 3397 Sequence operation
    数据库管理工具navicat的使用
    javascript封装animate动画
    关于webpack没有全局安装下的启动命令
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/11057591.html
Copyright © 2020-2023  润新知