您的位置:首页 > 其它

UVa10779 Collectors Problem(最大流)

2015-12-19 17:13 218 查看
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=33631

【思路】

最大流。

构图:

1 建立m个x点表示贴纸,n-1个y点表示Bob的朋友,ST表示源汇点。

2 S向x[j]连一条容量为sum[0][j]的边,表示Bob可以换出如是贴纸。

3 y[j]向x[i]连容量为1的边当且仅当i没有j,x[i]向y[j]连容量为sum[i][j]-1的边。

   4 x[i]向T连一条容量为1的边统计不同种类的数目。

【代码】

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;

const int maxn = 100+10;
const int INF = 1e9;

struct Edge{
int u,v,cap,flow;
};
struct Dinic {
int n,m,s,t;
bool vis[maxn];
int d[maxn],cur[maxn];
vector<int> G[maxn];
vector<Edge> es;

void init(int n) {
this->n=n;
es.clear();
for(int i=0;i<n;i++) G[i].clear();
}
void AddEdge(int u,int v,int cap) {
es.push_back((Edge){u,v,cap,0});
es.push_back((Edge){v,u,0,0});
m=es.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}

bool BFS() {
queue<int> q;
memset(vis,0,sizeof(vis));
q.push(s); vis[s]=1; d[s]=0;
while(!q.empty()) {
int u=q.front(); q.pop();
for(int i=0;i<G[u].size();i++) {
Edge& e=es[G[u][i]];
int v=e.v;
if(!vis[v] && e.cap>e.flow) {
vis[v]=1;
d[v]=d[u]+1;
q.push(v);
}
}
}
return vis[t];
}
int DFS(int u,int a) {
if(u==t || a==0) return a;
int flow=0,f;
for(int& i=cur[u];i<G[u].size();i++){
Edge& e=es[G[u][i]];
int v=e.v;
if( d[v]==d[u]+1 && (f=DFS(v,min(a,e.cap-e.flow)))>0 ) {
e.flow+=f;
es[G[u][i]^1].flow-=f;
flow+=f,a-=f;
if(!a) break;
}
}
return flow;
}
int Maxflow(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 T,n,m;
int sum[maxn][maxn];

int main() {
scanf("%d",&T);
int kase=0;
while(T--) {
scanf("%d%d",&n,&m);
dinic.init(n+m+1);
memset(sum,0,sizeof(sum));
int a,b;
for(int i=0;i<n;i++) {
scanf("%d",&a);
for(int j=0;j<a;j++){
scanf("%d",&b);
sum[i][b-1]++;
}
}
int s=n+m-1,t=n+m;
for(int i=0;i<m;i++) {
if(sum[0][i]) dinic.AddEdge(s,i,sum[0][i]);
dinic.AddEdge(i,t,1);
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++) {
if(!sum[i][j]) dinic.AddEdge(j,i+m-1,1);
if(sum[i][j]>1) dinic.AddEdge(i+m-1,j,sum[i][j]-1);
}
printf("Case #%d: %d\n",++kase,dinic.Maxflow(s,t));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: