【网络流24题】试题库问题

对于每个试题只能属于一个类型的限制,我们从原点向试题连1
然后把每个试题向类别连边,类别向汇点连要求量就可以了
挺板子的说?

/*
@Date    : 2019-08-28 14:20:04
@Author  : Adscn (adscn@qq.com)
@Link    : https://www.cnblogs.com/LLCSBlog
*/
#include<bits/stdc++.h>
using namespace std;
#define IL inline
#define RG register
#define gi getint()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
IL int getint()
{
    RG int xi=0;
    RG char ch=gc;
    bool f=0;
    while(ch<'0'||ch>'9')ch=='-'?f=1:f,ch=gc;
    while(ch>='0'&&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;
    return f?-xi:xi;
}
template<typename T>
IL void pi(T k,char ch=0)
{
    if(k<0)k=-k,putchar('-');
    if(k>=10)pi(k/10,0);
    putchar(k%10+'0');
    if(ch)putchar(ch);
}
const int N=1e3+7;
int S,T;
struct edge{int v,nxt,flow;}e[N*100];
int head[N*2],cur[N*2],cnt;
inline void add(int u,int v,int f){e[++cnt]=(edge){v,head[u],f},head[u]=cnt;}
inline void link(int u,int v,int flow){add(u,v,flow),add(v,u,0);}
int dep[N];
inline bool bfs(){
    memset(dep,-1,sizeof dep);
    static int Q[N<<1];
    int l=1,r=0;
    Q[++r]=S,dep[S]=0;
    while(l<=r)
        for(int p=Q[l++],i=head[p],v;~i;i=e[i].nxt)
            if(e[i].flow&&dep[v=e[i].v]==-1)
                dep[v]=dep[p]+1,Q[++r]=v;
    return ~dep[T];
}
inline int dfs(int p,int restflow){ 
    if(p==T||!restflow)return restflow;
    int sumflow=0;
    for(int &i=cur[p],flow,v;~i;i=e[i].nxt)
        if(e[i].flow&&dep[v=e[i].v]==dep[p]+1&&(flow=dfs(v,min(e[i].flow,restflow))))
        {
            restflow-=flow,sumflow+=flow;
            e[i].flow-=flow,e[i^1].flow+=flow;
            if(!restflow)break;
        }
    return sumflow;
}
inline int dinic(void){
    int maxflow=0;
    while(bfs())memcpy(cur,head,sizeof head),maxflow+=dfs(S,INT_MAX);
    return maxflow;
}
inline void init(){memset(head,cnt=-1,sizeof head);}
queue<int>Output[50];
int main(void)
{
    int k=gi,n=gi;
    init();
    S=k+n+1,T=k+n+2;
    int m=0;
    for(int i=1;i<=k;++i)
    {
        int t=gi;
        m+=t;
        link(n+i,T,t);
    }
    for(int i=1;i<=n;++i){
        int num=gi;
        while(num--)link(i,n+gi,1);
    }
    for(int i=1;i<=n;++i)link(S,i,1);
    int mx=dinic();
    if(mx!=m)return printf("No Solution!"),0;
    for(int i=1;i<=n;++i)
        for(int j=head[i];~j;j=e[j].nxt)
            if((j&1)==0&&!e[j].flow)
            {   
                Output[e[j].v-n].push(i);
                break;
            }
    for(int i=1;i<=k;++i){
        pi(i,':');
        while(!Output[i].empty())pi(Output[i].front(),' '),Output[i].pop();
        puts("");
    }
    return 0;
}

转载于:https://www.cnblogs.com/LLCSBlog/p/11424922.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值