Luo Gu P2763 solution to a problem

Tucao about: Honey UKE What is this stuff? !


Topic analysis:

  1. Title observation surface, 对于给定的组卷要求,计算满足要求的组卷方案can be found which is a significant conditions of the bipartite graph matching problem, then consider modeling.

    • Build a super source, a super sink; questions connected with the source connected to the sink type.

    • Focus is on the number of questions the type of modeling. From sensibility to understand what, in fact, this has meant a little limiting, and each type requires only so many question the amount can not exceed, so when considering the type and the Meeting Point will be connected to the capacity of several types of questions, when calculate the maximum amount of flow will be locked title, the title will be able to meet the requirements of the surface. (I hope you can understand what I mean \ (QwQ \) )

    • The last figure is: Super source connected with questions, a capacity of 1; questions connected with the corresponding type, capacity 1; super connected sink type, capacity type number of the title. Specifically, the super source \ (S \) nodes \ (1 \) , node questions \ (2-n-1 + \) , the node type \ (n + 2-n + k + 1 \) Super sink \ (T \) nodes \ (n-K + 2 + \) .
  2. After modeling is complete, consider recording program.
    • Since \ (Dinic \) algorithm by \ (Xor \; 1 \) to complete the forward and reverse sides of the transition edge, so that the forward edge \ (e [i] .to \ ) is the end of the path, trans to edge \ (e [i \; Xor \; 1] .to \) is the starting point of the path, it is possible to enumerate each side to locate the appropriate node.
    • And because of the reverse edges \ (e [i \; Xor \; 1] .v \) is initialized to 0, when the \ (e [i \; Xor \; 1] .v \ neq0 \) , i.e. representatives this side is the side ran maximum flow, corresponding to this edge was also matched.
    • The last case excluded super super source and sink points.
  3. If \ (Dinic \) ran down again, ans (ie, the maximum flow) is still zero, then this data is not the answer (ie, output "No Solution!").


code (with detailed notes):

#include<bits/stdc++.h>
#define Maxn 4010
#define Maxm 10010
#define int long long 
using namespace std;
int k,n;
inline void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
int S,T;
int ans=0,dep[Maxn];
struct edge
{
    int to,next,v;
}e[Maxm<<1];//一定注意要开两倍空间(正反两条边) 
int head[Maxn],ei=1;//一定注意这里的ei为奇数 
void add(int x,int y,int v)
{
    ei++;
    e[ei].to=y;
    e[ei].v=v;
    e[ei].next=head[x];
    head[x]=ei;
}
int bfs()
{
    queue<int>qu;
    memset(dep,0,sizeof(dep));
    dep[S]=1;
    qu.push(S);
    while(!qu.empty())
    {
        int fr=qu.front();
        qu.pop();
        for(int i=head[fr];i;i=e[i].next)
        {
            int to=e[i].to;
            if(dep[to]!=0||e[i].v==0) continue;
            qu.push(to);
            dep[to]=dep[fr]+1;
        }
    }
    return dep[T]!=0;
}
int dfs(int from,int maxflow)
{
    if(from==T) return maxflow;
    int flow=0;
    for(int i=head[from];i;i=e[i].next)
    {
        int to=e[i].to;
        if(dep[to]!=dep[from]+1||e[i].v==0) continue;
        int rst=dfs(to,min(maxflow-flow,e[i].v));
        if(rst==0) dep[to]=0;
        e[i].v-=rst;
        e[i^1].v+=rst;
        flow+=rst;
        if(flow==maxflow) break;
    }
    return flow;
}
void dinic()
{
    while(bfs())
    {
        ans+=dfs(S,LLONG_MAX);
    }
}
signed main()
{
    read(k),read(n);
    S=1,T=k+n+2;//超级源点与超级汇点 
    for(int i=1;i<=n;i++)
    {
        add(S,i+1,1);
        add(i+1,S,0);
        //超级源点与试题相连,容量为1 
    }
    for(int i=1,x;i<=k;i++)
    {
        read(x);
        add(i+n+1,T,x);
        add(T,i+n+1,0);
        //类型与超级汇点相连,容量为类型的题数 
    }
    for(int i=1,p;i<=n;i++)
    {
        read(p);
        for(int j=1,x;j<=p;j++)
        {
            read(x);
            add(i+1,x+n+1,1);
            add(x+n+1,i+1,0);
            //类型与对应的试题相连,容量为1
        }
    }
    dinic();//跑dinic 
    if(ans==0)//没有答案 
    {
        puts("No Solution!");
        return 0;
    } 
    for(int num=1;num<=k;num++)//枚举所有类型 
    {
        printf("%lld:",num);
        for(int i=2;i<=ei;i+=2)//枚举每一条边来找到相应的节点 
        {
            if(e[i].to!=S&&e[i].to!=T&&e[i^1].to!=S&&e[i^1].to!=T)//排除掉超级源点与超级汇点的情况
            {
                if(e[i^1].v!=0)//这条边已经被匹配了 
                {
                    if(e[i].to-n-1==num)//判断是否为当前类型 
                    {
                        printf("%lld ",e[i^1].to-1);
                    }
                }
            }
        }
        printf("\n");
    }
    return 0;
}

Network flow Note:

  1. The key is to network flow modeling, is also the essence of modeling. Like this question as a bipartite graph matching problem can be taken to modeling the way I used: maximum matching = maximum flow .
  2. When initializing the former star of the counter, it must be as odd . Because the n th side of the forward side, the n + 1 reverse side edges, to achieve the e [i] a forward edge, e [i ^ 1] is a reverse side, it is necessary to ensure that the forward edge i is an odd number, i.e., the counter is initialized to be an odd number.
  3. Star forward the number of sides must open twice as much space as a positive side, a reverse side.

Guess you like

Origin www.cnblogs.com/nth-element/p/11313897.html