题意:
思路:
【问题分析】
二分图多重匹配问题,用最大流解决。
【建模方法】
建立二分图,每个类别为X集合中的顶点,每个题为Y集合中的顶点,增设附加源S和汇T。
1、从S向每个Xi连接一条容量为该类别所需数量的有向边。
2、从每个Yi向T连接一条容量为1的有向边。
3、如果一个题i属于一个类别j,连接一条从Xj到Yi容量为1的有向边。
求网络最大流,如果最大流量等于所有类别所需之和,则存在解,否则无解。对于每个类别,从X集合对应点出发的所有满流边,指向的B集合中的顶点就是该类别的所选的题(一个可行解)。
【建模分析】
二分图多重匹配问题。X,Y集合之间的边容量全部是1,保证两个点只能匹配一次,源汇的连边限制了每个点匹配的个数。求出网络最大流,如果流量等于X集合所有点与S边容量之和,那么则说明X集合
每个点都有完备的多重匹配。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef long double ld; 7 typedef pair<int,int> PII; 8 typedef pair<ll,ll> Pll; 9 typedef vector<int> VI; 10 typedef vector<PII> VII; 11 typedef pair<ll,ll>P; 12 #define N 100010 13 #define M 1000000 14 #define INF 1e9 15 #define fi first 16 #define se second 17 #define MP make_pair 18 #define pb push_back 19 #define pi acos(-1) 20 #define mem(a,b) memset(a,b,sizeof(a)) 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 23 #define lowbit(x) x&(-x) 24 #define Rand (rand()*(1<<16)+rand()) 25 #define id(x) ((x)<=B?(x):m-n/(x)+1) 26 #define ls p<<1 27 #define rs p<<1|1 28 29 const ll MOD=1e9+7,inv2=(MOD+1)/2; 30 double eps=1e-6; 31 int dx[4]={-1,1,0,0}; 32 int dy[4]={0,0,-1,1}; 33 34 VI c[N]; 35 int head[N],vet[N],len[N],nxt[N],a[N],dis[N],s,S,T,tot; 36 37 int read() 38 { 39 int v=0,f=1; 40 char c=getchar(); 41 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 42 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 43 return v*f; 44 } 45 46 void add(int a,int b,int c) 47 { 48 nxt[++tot]=head[a]; 49 vet[tot]=b; 50 len[tot]=c; 51 head[a]=tot; 52 53 nxt[++tot]=head[b]; 54 vet[tot]=a; 55 len[tot]=0; 56 head[b]=tot; 57 } 58 59 bool bfs() 60 { 61 queue<int>q; 62 rep(i,1,s) dis[i]=-1; 63 q.push(S),dis[S]=0; 64 while(!q.empty()) 65 { 66 int u=q.front(); 67 q.pop(); 68 int e=head[u]; 69 while(e) 70 { 71 int v=vet[e]; 72 if(len[e]&&dis[v]==-1) 73 { 74 dis[v]=dis[u]+1; 75 q.push(v); 76 } 77 e=nxt[e]; 78 } 79 } 80 return dis[T]!=-1; 81 } 82 83 int dfs(int u,int aug) 84 { 85 if(u==T) return aug; 86 int e=head[u],val=0,flow=0; 87 while(e) 88 { 89 int v=vet[e]; 90 if(len[e]&&dis[v]==dis[u]+1) 91 { 92 int t=dfs(v,min(len[e],aug)); 93 if(!t) 94 { 95 e=nxt[e]; 96 continue; 97 } 98 flow+=t; 99 aug-=t; 100 len[e]-=t; 101 len[e^1]+=t; 102 if(!aug) break; 103 } 104 e=nxt[e]; 105 } 106 if(!flow) dis[u]=-1; 107 return flow; 108 } 109 110 int maxflow() 111 { 112 int res=0; 113 while(bfs()) res+=dfs(S,INF); 114 return res; 115 } 116 117 int main() 118 { 119 //freopen("1.in","r",stdin); 120 //freopen("1.out","w",stdout); 121 int K=read(),n=read(); 122 s=K+n; 123 S=++s,T=++s; 124 rep(i,1,K) 125 { 126 a[i]=read(); 127 add(i+n,T,a[i]); 128 } 129 rep(i,1,n) 130 { 131 int x=read(); 132 add(S,i,1); 133 rep(j,1,x) 134 { 135 int y=read(); 136 add(i,y+n,1); 137 } 138 } 139 int sum=0; 140 rep(i,1,n) sum+=a[i]; 141 int flow=maxflow(); 142 //printf("sum=%d flow=%d ",sum,flow); 143 if(sum!=flow) printf("No Solution! "); 144 else 145 { 146 rep(i,1,n) 147 { 148 int e=head[i]; 149 while(e) 150 { 151 int v=vet[e]; 152 if(len[e]&&c[v-n].size()<a[v-n]) 153 { 154 c[v-n].pb(i); 155 break; 156 } 157 e=nxt[e]; 158 } 159 } 160 rep(i,1,K) 161 { 162 printf("%d: ",i); 163 for(int j=0;j<c[i].size();j++) printf("%d ",c[i][j]); 164 printf(" "); 165 } 166 } 167 return 0; 168 }