1280: Emmy卖猪pigs
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 279 Solved: 182
[Submit][Status][Discuss]
Description
Emmy在一个养猪场工作。这个养猪场有M个锁着的猪圈,但Emmy并没有钥匙。顾客会到养猪场来买猪,一个接着一个。每一位顾客都会有一些猪圈的钥匙,他们会将这些猪圈打开并买走固定数目的猪。 所有顾客有的钥匙和他们需要买猪的数量在事先都告诉了Emmy,于是Emmy要订一个计划,使得卖出去的猪最多。 买卖的过程是这样的:一个顾客前来,并打开所有他可以打开的猪圈。然后Emmy从这些猪圈里牵出固定数目的猪卖给顾客(最多只能和顾客需要数相等),并可以重新安排这些开着的猪圈中的猪。 每个猪圈可以存放任意数目的猪。 写一个程序,使得Emmy能够卖出去尽可能多的猪。
Input
第一行有两个整数:M和N,表示猪圈数和顾客数。 第二行有M个整数,表示每个猪圈初始时有多少猪。 接下来的N行按照前来的次序描述了每一个顾客,每行的格式如下: A K1 K2…KA B A表示该顾客拥有的钥匙数,K1...KA表示每个钥匙所对应的猪圈,B表示该顾客需要购买的猪的数目。
Output
仅包含一个整数,即最多能卖出去的猪的数目。
Sample Input
3 3
3 1 10
2 1 2 2
2 1 3 3
1 2 6
3 1 10
2 1 2 2
2 1 3 3
1 2 6
Sample Output
7
HINT
1 ≤ M ≤ 1000
1 ≤ N ≤ 100
【网络流建模汇总T1】
/************************************************************** Problem: 1280 User: gryz2016 Language: C++ Result: Accepted Time:0 ms Memory:2472 kb ****************************************************************/ //S向第一个打开某猪圈的人连边,容量为这个猪圈里猪的数量 //后边的打开这个猪圈的人从第一个打开这个猪圈的人那里连边过来,容量为INF //因为猪圈里的猪是可以随意调动的嘛 //然后更新打开这个猪圈的人 //不更新不是不对,但是会慢 //然后这个人向汇点连边,容量为他要买的猪的数量 //画个图会很清晰。 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; int n,m; int head[105],from[105],num_edge; int last[1005]; int w[1005]; int dep[105]; struct Edge { int v,flow,nxt; }edge[100005]; inline int read() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) f=c=='-'?-1:f; for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num*f; } inline void add_edge(int u,int v,int w) { edge[++num_edge].v=v; edge[num_edge].flow=w; edge[num_edge].nxt=head[u]; head[u]=num_edge; } inline bool bfs() { for(int i=0;i<=n;++i) from[i]=head[i],dep[i]=0; queue<int> que; int now,v; dep[0]=1; que.push(0); while(!que.empty()) { now=que.front(),que.pop(); for(int i=head[now];i;i=edge[i].nxt) { v=edge[i].v; if(!dep[v]&&edge[i].flow) { dep[v]=dep[now]+1; if(v==n) return 1; que.push(v); } } } return 0; } int dfs(int now,int flow) { if(now==n||!flow) return flow; int outflow=0,v,tmp; for(int &i=from[now];i;i=edge[i].nxt) { v=edge[i].v; if(dep[v]!=dep[now]+1) continue; tmp=dfs(v,min(flow,edge[i].flow)); flow-=tmp; outflow+=tmp; edge[i].flow-=tmp; edge[i^1].flow+=tmp; if(!flow) return outflow; } dep[now]=0; return outflow; } int main() { num_edge=1; m=read(),n=read(); for(int i=1;i<=m;++i) w[i]=read(); int a,b; for(int i=1;i<=n;++i) { a=read(); while(a--) { b=read(); if(!last[b]) //这个猪圈是第一次被打开 add_edge(0,i,w[b]), add_edge(i,0,0); else add_edge(last[b],i,0x7fffffff), //向上一个打开这个猪圈的人连边 add_edge(i,last[b],0); last[b]=i; } b=read(); add_edge(i,n+1,b); add_edge(n+1,i,0); } ++n; int ans=0; while(bfs()) ans+=dfs(0,0x7fffffff); printf("%d",ans); return 0; }