码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu P1231 教辅的组成 题解

时间:2019-08-18 13:41:09      阅读:59      评论:0      收藏:0      [点我收藏+]

标签:get   register   无语   for   solution   memcpy   size   mat   虚拟   

闲扯

这个题还是挺裸的一个最大流,只是需要建个图就行了。

可是为什么我连边都能连反啊。。。。

Solution

因为两组关系里面都知道书,所以书放中间,两边分别放练习册和答案。

虚拟一个超级源点,分别连向 \(N1\) 本练习册,每条边的流量都为 \(1\) ,因为每个都只能用来配对一次(下同)。

虚拟一个超级汇点,分别由 \(N3\) 个答案连向它,流量为 \(1\)

按照题目给出的对应关系,由练习册连向书,由书连向答案,流量均为 \(1\) 。但是每本书只能用一次,所以我们选用拆点的策略,将一本书拆成两本,然后再连上一条流量为 \(1\) 的边,这样就保证了每本书只用一次。

然后直接上模板,\(Dinic\) 直接一波带走。

时间复杂度: \(O(n^2\cdot m)\) 实则不然,其实是 O(玄学)的

Code:

#include<bits/stdc++.h>
#define del(a,i) memset(a,i,sizeof(a))
#define ll long long
#define inl inline
#define il inl void
#define it inl int
#define ill inl ll
#define re register
#define ri re int
#define rl re ll
#define mid ((l+r)>>1)
#define lowbit(x) (x&(-x))
#define INF 0x3f3f3f3f
using namespace std;
template<class T>il read(T &x){
    int f=1;char k=getchar();x=0;
    for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
    for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
    x*=f;
}
template<class T>il print(T x){
    if(x/10) print(x/10);
    putchar(x%10+'0');
}
ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
it qpow(int x,int m,int mod){
    int res=1,bas=x%mod;
    while(m){
        if(m&1) res=(res*bas)%mod;
        bas=(bas*bas)%mod,m>>=1;
    }
    return res%mod;
}
const int MAXN = 4e4+5;
int n1,n2,n3,m,u,v,s,t,cur[MAXN],head[MAXN],num_edge=-1,dis[MAXN];
struct Edge{
    int next,to,w;
    Edge(){}
    Edge(int next,int to,int w):next(next),to(to),w(w){}
}edge[1000005];
il add_edge(int u,int v,int w){
    edge[++num_edge]=Edge(head[u],v,w),head[u]=num_edge;
    edge[++num_edge]=Edge(head[v],u,0),head[v]=num_edge;
}
inl bool BFS(int s,int t){
    queue<int> q;q.push(s);
    del(dis,0),dis[s]=1;
    while(!q.empty()){
        ri pos=q.front();q.pop();
        for(ri i=head[pos];i!=-1;i=edge[i].next)
            if(!dis[edge[i].to]&&edge[i].w>0){
                dis[edge[i].to]=dis[pos]+1;
                if(edge[i].to==t) return true;
                q.push(edge[i].to);
            }
    }
    return false;
}
it DFS(int now,int t,int flow){
    if(now==t) return flow;
    ri s=0,k;
    for(ri &i=cur[now];i!=-1;i=edge[i].next)
        if(dis[edge[i].to]==dis[now]+1&&edge[i].w>0){
            k=DFS(edge[i].to,t,min(flow-s,edge[i].w));
            s+=k,edge[i].w-=k,edge[i^1].w+=k;
            if(s==flow) break;
        }
    if(s==0) dis[now]=0;
    return s;
}
it Dinic(int s,int t){
    ri ans=0;
    while(BFS(s,t)){
        memcpy(cur,head,sizeof(head));
        ans+=DFS(s,t,INF);
    }
    return ans;
}
int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(n1),read(n2),read(n3),t=n1*2+n2+n3+1,del(head,-1);
    for(ri i=1;i<=n1;++i) add_edge(i+n2,i+n1+n2,1);
    for(ri i=1;i<=n2;++i) add_edge(s,i,1);
    for(ri i=1;i<=n3;++i) add_edge(i+n1*2+n2,t,1);
    read(m);
    for(ri i=1;i<=m;++i) read(u),read(v),add_edge(v,u+n2,1);
    read(m);
    for(ri i=1;i<=m;++i) read(u),read(v),add_edge(u+n2+n1,v+n2+n1*2,1);
    printf("%d",Dinic(s,t));
    return 0;
}

总结

套路啊,都是套路。。

我已经无语了。。

Luogu P1231 教辅的组成 题解

标签:get   register   无语   for   solution   memcpy   size   mat   虚拟   

原文地址:https://www.cnblogs.com/TheShadow/p/11372091.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!