zoukankan      html  css  js  c++  java
  • P2763 试题库问题(dinic)

    P2763 试题库问题

    dinic

    搞个虚拟源点和汇点,瞎建建边就好辣。

    偷张图↓↓

    如果没满流就是无解辣

    输出方案咋办呢?

    枚举每种类型,蓝后枚举它们的边

    如果该边被使用了(通过判断反向边的流量),且连接的另一点不是汇点

    那么就找到一个被用的题了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    inline int Min(int a,int b){return a<b?a:b;}
    void read(int &x){
        static char c=getchar();x=0;
        while(c<'0'||c>'9') c=getchar();
        while('0'<=c&&c<='9') x=x*10+(c^48),c=getchar();
    }
    #define N 1050
    #define M 210000
    int n,m,k,S,T,d[N],cur[N]; bool vis[N];
    int cnt=1,hd[N],nxt[M],ed[N],poi[M],val[M];
    queue <int> h;
    void adde(int x,int y,int v){
        nxt[ed[x]]=++cnt; hd[x]=hd[x]?hd[x]:cnt;
        ed[x]=cnt; poi[cnt]=y; val[cnt]=v;
    }
    bool bfs(){
        memset(vis,0,sizeof(vis));
        h.push(S); vis[S]=1; d[S]=0;
        while(!h.empty()){
            int x=h.front(); h.pop();
            for(int i=hd[x];i;i=nxt[i]){
                int to=poi[i];
                if(!vis[to]&&val[i]>0){
                    vis[to]=1; d[to]=d[x]+1;
                    h.push(to);
                }
            }
        }return vis[T];
    }
    int dfs(int x,int a){
        if(x==T||a==0) return a;
        int f,F=0;
        for(int &i=cur[x];i&&a;i=nxt[i]){
            int to=poi[i];
            if(d[to]==d[x]+1&&(f=dfs(to,Min(a,val[i])))>0)
                a-=f,F+=f,val[i]-=f,val[i^1]+=f;
        }return F;
    }
    int dinic(){
        int re=0;
        while(bfs()){
            for(int i=1;i<=T;++i) cur[i]=hd[i];
            re+=dfs(S,1e9);
        }return re;
    }
    inline void link(int x,int y,int v){adde(x,y,v),adde(y,x,0);}
    int main(){
        read(k);read(n); register int i,j,q;
        S=n+k+1; T=S+1;
        for(i=1;i<=k;++i) read(q),m+=q,link(i+n,T,q);
        for(i=1;i<=n;++i){
            read(j); link(S,i,1);
            while(j--) read(q),link(i,q+n,1);
        }
        if(dinic()!=m){puts("No Solution!");return 0;}
        for(i=1;i<=k;++i){
            printf("%d:",i);
            for(j=hd[i+n];j;j=nxt[j])
                if(poi[j]!=T&&val[j])
                    printf(" %d",poi[j]);
            printf("
    ");
        }return 0;
    }
  • 相关阅读:
    第十一章关联容器
    第十章泛型算法
    第九章
    第八章
    阅读记录
    java.lang.Class阅读笔记
    java.time包阅读笔记
    CLion运行多个main函数
    c++中lower_bound和upper_bound中的comp参数
    如何写dfs
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10575232.html
Copyright © 2011-2022 走看看