网络流24题:试题库问题

来源:互联网 发布:已备案的域名转让 编辑:程序博客网 时间:2024/05/20 00:09

传送门
这个题好像比较水。
每个种类向汇点连容量为所需求的数量的边
然后每个试题向可以选的种类连容量为1的边
再从源点向每个试题连容量为1的边,然后dinic
过程中记录一下转移的目标节点,然后输出路径就好了
判无解不用我说了吧。
代码:

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<cstdlib>#include<vector>#define ll long longusing namespace std;inline int read(){    int x=0;char ch=' ';int f=1;    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();    if(ch=='-')f=-1,ch=getchar();    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();    return x*f;}const int N=2005,M=N*10;int k,n,sum,tot=-1,s,t;int head[N],d[N],q[N],cur[N],Nxt[N],Next[M],to[M],flow[M];inline void addedge(int x,int y,int c){    to[++tot]=y;Next[tot]=head[x];flow[tot]=c;head[x]=tot;    to[++tot]=x;Next[tot]=head[y];flow[tot]=0;head[y]=tot;}inline bool bfs(){    for(int i=s;i<=t;i++)d[i]=0x3f3f3f3f;    int l=1,r=1;d[s]=0;q[1]=s;    while(l<=r){        int x=q[l++];        for(int i=head[x];i!=-1;i=Next[i]){            int u=to[i];            if(flow[i]&&d[u]>d[x]+1){                d[u]=d[x]+1;                q[++r]=u;            }        }    }    return d[t]!=0x3f3f3f3f;}inline int dfs(int x,int a){    if(x==t||!a)return a;    int F=0,f;    for(int &i=cur[x];i!=-1;i=Next[i]){        int u=to[i];        if(flow[i]&&d[u]==d[x]+1&&(f=dfs(u,min(a,flow[i])))>0){            flow[i]-=f;            flow[i^1]+=f;            F+=f;            a-=f;            Nxt[x]=u;            if(!a)return F;        }    }    return F;}inline int dinic(){    int F=0;    while(bfs()){        for(int i=s;i<=t;i++)cur[i]=head[i];        F+=dfs(s,0x3f3f3f3f);    }    return F;}vector<int> T[N];int main(){    memset(head,-1,sizeof(head));    k=read();n=read();s=0;t=n+k+1;    for(int i=1;i<=k;i++){        int v=read();        sum+=v;        addedge(n+i,t,v);    }    for(int i=1;i<=n;i++){        int cnt=read();        addedge(s,i,1);        while(cnt--){            int v=read();            addedge(i,n+v,1);        }    }    int ans=dinic();    if(ans!=sum)printf("No Solution!");    else{        for(int i=1;i<=n;i++){            if(!Nxt[i])continue;            T[Nxt[i]-n].push_back(i);        }        vector<int>::iterator it;        for(int i=1;i<=k;i++){            printf("%d: ",i);            for(it=T[i].begin();it!=T[i].end();++it){                printf("%d ",*it);            }            putchar('\n');        }    }    return 0;}
原创粉丝点击