/*
有 M 个猪圈(M ≤ 1000),每个猪圈里初始时有若干头猪。
一开始所有猪圈都是关闭的。
依次来了 N 个顾客(N ≤ 100),每个顾客分别会打开指定的几个猪圈,从中买若干头猪。
每个顾客分别都有他能够买的数量的上限。
每个顾客走后,他打开的那些猪圈中的猪,都可以被任意地调换到其它开着的猪圈里,然后所有猪圈重新关上。
问总共最多能卖出多少头猪。
输入:
m n
m个数表示猪圈住的个数
n行:钥匙个数,哪些钥匙,要买多少猪。
重在建图呀
每个顾客分别用一个结点来表示。
• 对于每个猪圈的第一个顾客,从源点向他连一条边,容量就是该猪圈里的猪的初始数量。如果从源点到一名顾客有多条边,则可以把它们合并成一条,容量相加。
• 对于每个猪圈,假设有n个顾客打开过它,则对所有整数i∈[1, n),从该猪圈的第i个顾客向第i + 1个顾客连一条边,容量为∞。(不一要相邻)
• 从各个顾客到汇点各有一条边,容量是各个顾客能买的数量上限。
因为顾客买猪时可以把要买的圈都打开,所以从源点建边时不用区分不同猪圈,只要把可以购买的猪的数量建边就可以了
至于后续要买猪的,因为前一顾客买猪时把圈打开过,所以那几个猪圈的猪是可以随便调的,又没有放猪的容量限制,
所以可以看成一个整体,跟在上一个顾客后面建边
需要注意的是,本题建的是有向图。
而且点中只有源点,汇点和顾客们。
sample input
3 3
3 1 10
2 1 2 2
2 1 3 3
1 2 6
建图找本质,学会整合节点,有相通的化为一点。
*/
//晕死,我没有整合到原点的边居然也A了。。。。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#define maxn 120
#define INF 0x3fffffff
using namespace std;
int num[maxn];
int nu[1010];//是猪圈数,不是人数。。。。搞得我不是RE就是WA
int vis[1010][maxn];
int need[maxn];
int cap[1010];
struct Dinic
{
int edgeNum,source,sink;
bool vis[maxn];
int d[maxn];
int cur[maxn];
int mark[maxn];
struct edge
{
int from,to,cap,flow;
};
vector<edge> edges;
vector<int> mapt[maxn];
void addEdge(int from,int to,int cap){
//pf("%d %d %d\n",from,to,cap);
edges.push_back((edge){from,to,cap,0});
edges.push_back((edge){to,from,0,0});
edgeNum = edges.size();
mapt[from].push_back(edgeNum-2);
mapt[to].push_back(edgeNum-1);
}
bool bfs()///更新可行流
{
memset(vis,0,sizeof vis);
queue<int> q;
q.push(source);
d[source] =0; vis[source] =1;
while(!q.empty()){
int x = q.front(); q.pop();
for(int i=0;i<mapt[x].size();i++){
edge& e = edges[mapt[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[sink];
}
int dfs(int x,int a){
if(x==sink||a==0) return a;
int flow=0,f;
for(int& i=cur[x];i<mapt[x].size();i++)
{
edge& e = edges[mapt[x][i]];
if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){
e.flow += f;
edges[mapt[x][i]^1].flow -= f;
flow += f;
a -= f;
if(a==0) break;
}
}
return flow;
}
int maxFlow(int source,int sink){
this->sink = sink; this->source = source;
int flow = 0;
while(bfs()){
memset(cur,0,sizeof cur);
flow += dfs(source,INF);
}
return flow;
}
};
int main()
{
int n,m;
while(scanf("%d%d",&m,&n)!=EOF)
{
int source=0;
int dest=n+1;
Dinic dinic;
memset(nu,0,sizeof(nu));
for(int i=1;i<=m;i++)
scanf("%d",&cap[i]);
for(int i=1;i<=n;i++)
{
int temp;
scanf("%d",&num[i]);
for(int j=1;j<=num[i];j++)
{
scanf("%d",&temp);
vis[temp][++nu[temp]]=i;
}
scanf("%d",&need[i]);
}
for(int i=1;i<=m;i++)///建图部分
dinic.addEdge(source,vis[i][1],cap[i]);
for(int i=1;i<=m;i++)
for(int j=1;j<nu[i];j++)
dinic.addEdge(vis[i][j],vis[i][j+1],INF);
for(int i=1;i<=n;i++)
dinic.addEdge(i,dest,need[i]);
cout<<dinic.maxFlow(source,dest)<<endl;///输出答案部分。
}
}
POJ 1149 网络流构图
最新推荐文章于 2018-08-03 10:36:47 发布