題目描述
There are n heroes and m monsters living in an island. The monsters became very vicious these days, so the heroes decided to diminish the monsters in the island. However, the i-th hero can only kill one monster belonging to the set Mi. Joe, the strategist, has k bottles of magic potion, each of which can buff one hero’s power and let him be able to kill one more monster. Since the potion is very powerful, a hero can only take at most one bottle of potion.
Please help Joe find out the maximum number of monsters that can be killed by the heroes if he uses the optimal strategy.
Input
The first line contains three integers n, m, k (1 ≤ n, m, k ≤ 500) — the number of heroes, the number of monsters and the number of bottles of potion.
Each of the next n lines contains one integer ti , the size of Mi, and the following ti integers Mi,j (1 ≤ j ≤ ti), the indices (1-based) of monsters that can be killed by the i-th hero (1 ≤ ti ≤ m, 1 ≤ Mi,j ≤ m).
Output
Print the maximum number of monsters that can be killed by the heroes.
Sample Input
sample input 1
3 5 2
4 1 2 3 5
2 2 5
2 1 2
sample input 2
5 10 2
2 3 10
5 1 3 4 6 10
5 3 4 6 8 9
3 1 9 10
5 1 3 6 7 10
Sample Output
sample output 1
4
sample output 2
7
題目分析
發現是匹配問題,思考將問題建圖后用最大流算法進行解決。
如果沒有k個藥水,則很明確,將問題轉化成一個二部圖,從源點到英雄,從英雄到怪獸,從怪獸到匯點,路徑上的容量都為1,則最大流就是殺死的最多的怪獸。
因為還有k個藥水,并且每一個英雄都只能拿一個藥水,我們從源點引出一個點,容量為k
,再從這個點到每個英雄引一條路徑,每條路徑容量為1
AC代碼
#include<iostream>
#include<cstring>
#include<cstdio>
#include<climits>
#include<algorithm>
#include<ctime>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<cmath>using namespace std;typedef long long ll;
const int MAXN=1020;
const int INF=0x3f3f3f3f;struct Edge
{int from,to,cap,flow;Edge(int _from,int _to,int _cap,int _flow):from(_from),to(_to),cap(_cap),flow(_flow){}
};
struct Dinic
{int s,t;vector<Edge> edges;vector<int> G[MAXN];int d[MAXN]; bool vis[MAXN]; int cur[MAXN];void addEdge(int from,int to,int cap){edges.push_back((Edge){from,to,cap,0});edges.push_back((Edge){to,from,0,0});int tt=edges.size();G[from].push_back(tt-2);G[to].push_back(tt-1);}bool BFS(){memset(vis,0,sizeof(vis));queue<int>Q;Q.push(s);d[s]=0;vis[s]=1;while(!Q.empty()){int x=Q.front(); Q.pop();for(int i=0;i<G[x].size();++i){Edge &e =edges[G[x][i]];if(!vis[e.to] && e.cap>e.flow){vis[e.to]=1;d[e.to]=d[x]+1;Q.push(e.to);}}}return vis[t];}int DFS(int x,int a){if(x==t || a==0) return a;int flow=0,f;for(int&i=cur[x];i<G[x].size();++i){Edge& e=edges[G[x][i]];if(d[x]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0){e.flow+=f;edges[G[x][i]^1].flow-=f;flow+=f;a-=f;if(a==0) break;}}return flow;}int MF(int s,int t){this->s=s; this->t=t;int flow=0;while(BFS()){memset(cur,0,sizeof(cur));flow+=DFS(s,INF);}return flow;}
}dinic;int n,m,k;int main()
{scanf("%d%d%d",&n,&m,&k);int tmp=n+m+1;int t=tmp+1;int s=0;dinic.addEdge(s,tmp,k);for(int i=1;i<=n;i++){dinic.addEdge(s,i,1); dinic.addEdge(tmp,i,1);int t,u; scanf("%d",&t);while(t--){scanf("%d",&u); dinic.addEdge(i,u+n,1);}}for(int i=1;i<=m;i++){dinic.addEdge(i+n,t,1);}printf("%d\n",dinic.MF(s,t));return 0;
}
經驗總結
第一次寫網絡流的題目。感覺就是在使用工具,如何正確地使用才是問題的關鍵,而不一定要求掌握工具怎么造出來的。這對當下我來說很重要。當然掌握工具的原理以后就能更好的使用工具。后面會花功夫具體去學習網絡流的原理的。