zoukankan      html  css  js  c++  java
  • [日常摸鱼]「网络流 24 题」试题库

    https://loj.ac/problem/6006

    题意:$n$道题每题有若干种类别,一共有$k$种类别,告诉你每种类别各自需要的题数,构造一种选题目的方案并输出方案。

    虽然题目好像没说不过一道题应该不能选多次…(反正我这么写的过掉了x

    这道题做下来感觉莫名的很爽233

    把每道题向其对应的类别连容量为1的边,源点向所有题也连容量为1的边,而所有类别向汇点连的边容量为该题所需要的题数。

    从源点到汇点跑一遍最大流,每次找到增广路我们要更新这条路上唯一的那个对应类别的结点,于是我们就想到用EK来实现这个过程啦。

    设所有类别需要的题数之和为$m$,我们顺便求出了最大流,显然如果最后最大流<$m$的话就无解了。否则的话就输出方案~

    我也不知道要不要排序反正随手排一个保平安…

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define rep(i,n) for(register int i=1;i<=n;i++)
    #define REP(i,a,b) for(register int i=a;i<=b;i++)
    using namespace std;
    const int N=1050;
    const int M=50005;
    const int INF=(~0u>>1);
    struct edge
    {
        int to,nxt,w;
        edge(int to=0,int nxt=0,int w=0):to(to),nxt(nxt),w(w){}
    }edges[M<<1];
    int n,m,k,cnt,s,t,st,ed,maxflow;
    int head[M<<1],infc[N],pre[N],ans[25][N],v[N],q[N],need[N];
    
    inline void addEdge(int u,int v,int w=1)
    {
        edges[++cnt]=edge(v,head[u],w);head[u]=cnt;
        edges[++cnt]=edge(u,head[v],0);head[v]=cnt;
    }
    #define cur edges[i].to
    inline bool bfs()
    {
        memset(v,0,sizeof v);v[s]=1;
        infc[s]=INF;st=ed=0;q[st++]=s;
        while(ed<st)
        {
            int k=q[ed++];
            for(register int i=head[k];i;i=edges[i].nxt)if(edges[i].w&&!v[cur])
            {
                v[cur]=1;q[st++]=cur;pre[cur]=i;
                infc[cur]=min(infc[k],edges[i].w);
                if(cur==t)return 1;
            }
        }
        return 0;
    }
    #undef cur
    inline void update()
    {
        int tmp=t;
        while(tmp!=s)
        {
            int i=pre[tmp];
            edges[i].w-=infc[t];
            edges[i^1].w+=infc[t];
            int now=tmp-n,cur=edges[i^1].to;
            if(1<=now&&now<=k)
                ans[now][++ans[now][0]]=cur;
            tmp=edges[i^1].to;
        }
        maxflow+=infc[t];
    }
    int main()
    {
        scanf("%d%d",&k,&n);s=n+k+1;t=s+1;cnt=1;
        rep(i,k)scanf("%d",&need[i]),m+=need[i];
        rep(i,n)
        {
            int p,x;scanf("%d",&p);
            rep(j,p)
            {
                scanf("%d",&x);
                addEdge(i,x+n);
            }
        }
        rep(i,n)addEdge(s,i);
        rep(i,k)addEdge(i+n,t,need[i]);
        while(bfs())update();
        if(maxflow!=m)printf("No Solution!");
        else
        {
            rep(i,k)
            {
                sort(ans[i]+1,ans[i]+ans[i][0]+1);
                printf("%d: ",i);rep(j,ans[i][0])printf("%d ",ans[i][j]);
                printf("
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    javascript运算符
    javascript字符串转数字
    javascript的变量声明和数据类型
    javascript的历史和入门
    CSS中定位
    CSS中盒子模型
    CSS操作表格的边框和表格的属性示例代码
    常用的CSS样式示例代码
    CSS伪类选择器
    CSS选择器
  • 原文地址:https://www.cnblogs.com/yoshinow2001/p/8424689.html
Copyright © 2011-2022 走看看