【网络流24题】No.7 试题库问题 (最大流,二分图多重匹配)

【题意】

  假设一个试题库中有 n 道试题。 每道试题都标明了所属类别。 同一道题可能有多个类别属性。现要从题库中抽取 m 道题组成试卷。并要求试卷包含指定类型的试题。 试设计一个
满足要求的组卷算法。

输入文件示例
input.txt
3 15
3 3 4
2 1 2
1 3
1 3
1 3
1 3
3 1 2 3
2 2 3
2 1 3
1 2
1 2
2 1 2
2 1 3
2 1 2
1 1
3 1 2 3

输出文件示例
output.txt
1: 1 6 8
2: 7 9 10
3: 2 3 4 5

【分析】

  二分图多重匹配, 应该是指 点可以选w[i]次,边只能选一次吧。

  这样就不能用匈牙利了吧。。[咦~~好像也可以,就是要记录所有w次匹配的是谁 然后枚举

  也可以把点拆开,然后做匈牙利,(有空再试试)

  嗯,最大流建边就很简单啦,那就不说了。。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
#define Maxn 1010
#define INF 0xfffffff struct node
{
int x,y,f,o,next;
}t[Maxn*];int len;
int first[Maxn]; int mymin(int x,int y) {return x<y?x:y;}
int mymax(int x,int y) {return x>y?x:y;} void ins(int x,int y,int f)
{
t[++len].x=x;t[len].y=y;t[len].f=f;
t[len].next=first[x];first[x]=len;t[len].o=len+;
t[++len].x=y;t[len].y=x;t[len].f=;
t[len].next=first[y];first[y]=len;t[len].o=len-;
} int st,ed;
queue<int > q;
int dis[Maxn];
bool bfs()
{
while(!q.empty()) q.pop();
memset(dis,-,sizeof(dis));
q.push(st);dis[st]=;
while(!q.empty())
{
int x=q.front();
for(int i=first[x];i;i=t[i].next) if(t[i].f>)
{
int y=t[i].y;
if(dis[y]==-)
{
dis[y]=dis[x]+;
q.push(y);
}
}
q.pop();
}
if(dis[ed]==-) return ;
return ;
} int ffind(int x,int flow)
{
if(x==ed) return flow;
int now=;
for(int i=first[x];i;i=t[i].next) if(t[i].f>)
{
int y=t[i].y;
if(dis[y]==dis[x]+)
{
int a=ffind(y,mymin(flow-now,t[i].f));
t[i].f-=a;
t[t[i].o].f+=a;
now+=a;
}
if(now==flow) break;
}
if(now==) dis[x]=-;
return now;
} void output()
{
for(int i=;i<=len;i+=)
printf("%d->%d %d\n",t[i].x,t[i].y,t[i].f);
} int max_flow()
{
int ans=;
while(bfs())
{
ans+=ffind(st,INF);
}
return ans;
} int op[Maxn][Maxn]; int main()
{
int k,n,m=;
scanf("%d%d",&k,&n);
st=n+k+;ed=st+;
len=;
memset(first,,sizeof(first));
for(int i=;i<=k;i++)
{
int x;
scanf("%d",&x);
m+=x;
ins(n+i,ed,x);
}
for(int i=;i<=n;i++)
{
int x;
scanf("%d",&x);
ins(st,i,);
while(x--)
{
int y;
scanf("%d",&y);
ins(i,y+n,);
}
}
int now=max_flow();
if(now<m) printf("No Solution!\n");
else
{
for(int i=;i<=k;i++) op[i][]=;
for(int i=;i<=len;i+=) if(t[i].x!=st&&t[i].y!=ed&&t[i].f==)
{
op[t[i].y-n][++op[t[i].y-n][]]=t[i].x;
}
for(int i=;i<=k;i++)
{
printf("%d: ",i);
for(int j=;j<=op[i][];j++)
printf("%d ",op[i][j]);printf("\n");
}
}
return ;
}

没special judge 测不了 哭泣。。

2016-11-04 14:53:36

上一篇:robotframework之上传功能


下一篇:add some template for ec-final