试题库问题(网络流24题)

题意

有n道题,每个题有一些类别属性,先现出k个属性各需要的题数,一道题只能在一种类别。

输出方案,没有则输出"No Solution!"

(2 <=k<= 20, k<=n<= 1000)

题解

还是比较基础,把试题和属性分成两部分,试题与属性之间连边流量为1,源点与试题之间连边流量为1,属性与汇点连边流量为需要的题数。

最后看最大流是否为总共需要的题数,输出方案则枚举看是否满流。

#include<bits/stdc++.h>
using namespace std;

const int maxn=1006;
const int maxm=1000006;
int n,m,k;
int cnt=1,s,t,head[maxn];
struct edge{
  int x,y,val,next;
}e[maxm];

template<class T>inline void read(T &x){
  x=0;char ch=getchar();
  while(!isdigit(ch)) ch=getchar();
  while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
}

void add(int x,int y,int val){
  e[++cnt]=(edge){x,y,val,head[x]};
  head[x]=cnt;
}

int d[maxn];

bool bfs(){
  queue<int> q;
  memset(d,0,sizeof(d));
  q.push(s);d[s]=1;
  while(!q.empty()){
    int x=q.front();
    q.pop();
    for(int i=head[x];i;i=e[i].next){
      int y=e[i].y;
      if(e[i].val&&!d[y]){
        d[y]=d[x]+1;
        if(y==t) return true;
        q.push(y);
      }
    }
  }
  return false;
}

int dfs(int x,int flow){
  if(x==t) return flow;
  int rest=flow,k;
  for(int i=head[x];i;i=e[i].next){
    int y=e[i].y;
    if(d[y]==d[x]+1&&e[i].val){
      k=dfs(y,min(rest,e[i].val));
      if(!k) d[y]=0;
      e[i].val-=k;
      e[i^1].val+=k;
      rest-=k;
    }
  }
  return flow-rest;
}

int dinic(){
  int res=0;
  while(bfs()) res+=dfs(s,0x3f3f3f);
  return res;
}

int main(){
  scanf("%d%d",&k,&n);
  s=0;t=k+n+1;
  for(int i=1;i<=k;i++){
    int x;read(x);
    add(i+n,t,x);
    add(t,i+n,0);
    m+=x;
  }
  for(int i=1;i<=n;i++){
    add(s,i,1);
    add(i,s,0);
    int tot;read(tot);
    for(int j=1;j<=tot;j++){
      int x;read(x);
      add(i,x+n,1);
      add(x+n,i,0);
    }
  }
  int ans=dinic();
  if(ans!=m) {printf("No Solution!");return 0;}
  for(int i=n+1;i<=n+k;i++){
    printf("%d: ",i-n);
    for(int j=head[i];j;j=e[j].next)
     if(e[j].val) printf("%d ",e[j].y);
    putchar(10);
  }
}
View Code
原文地址:https://www.cnblogs.com/sto324/p/11353522.html