UVA 10779 Collectors Problem(最大流)

来源:互联网 发布:mac 压感 编辑:程序博客网 时间:2024/04/30 07:12

题意:有T(T20)组数据。Bob在与他的n1(2n10)个同伴交换糖纸,一共有m(5m25)种糖纸。Bob希望能和同伴交换使得手上的糖纸数尽量多。他的同伴只会用手上的重复的交换手上没有的,并且他的同伴们之间不会产生交换。求出Bob能拥有的最大糖纸种数。


分析:

 最大流。

①:源点(Bob)->m种糖纸:cap是Bob持有贴纸数量。

②:所有同伴->m种糖纸:持有的该贴纸数量>=2,连一条边,cap是 糖纸数量 - 1。(只会换重复的贴纸)。

③:m种糖纸->所有同伴:没这种糖纸,连一条边,cap=1,。(只接受自己没有的贴纸)

④:m种糖纸->汇点:cap=1。




#include<iostream>#include<algorithm>#include<cstdio>#include<cmath>#include<cstring>#include<string>#include<vector>#include<cctype>#include<set>#include<map>#include<queue>#include<stack>#include<iomanip>#include<sstream>#include<limits>#define ll long long#define inf 0x3f3f3f3fusing namespace std;#define INF 0x7fffffffconst int maxn = 1e5+10;struct Edge{    int to , cap,rev;  // rev反向边};vector<Edge>G[maxn];int level[maxn],iter[maxn];  // 顶点到源点的标号   当前弧void add_edge(int from,int to,int cap) //cap容量{    G[from].push_back((Edge){to,cap,G[to].size()});    G[to].push_back((Edge){from,0,G[from].size()-1 });}void bfs(int s) // 分层{    memset(level,-1,sizeof(level));    queue<int>que;    level[s] = 0;    que.push(s);    while(!que.empty())    {        int v = que.front();que.pop();        for(int i = 0; i < G[v].size(); i++)        {            Edge &e = G[v][i];            if (e.cap>0 && level[e.to] < 0)            {                level[e.to] = level[v]+1;                que.push(e.to);            }        }    }}int dfs(int v, int t, int f) //寻增广路{    if (v==t) return f;    for(int &i = iter[v]; i < G[v].size(); i++)    {        Edge &e = G[v][i];        if (e.cap > 0 && level[v] < level[e.to])        {            int d = dfs(e.to , t, min(f,e.cap));            if (d > 0)            {                e.cap -= d;                G[e.to][e.rev].cap += d;                return d;            }        }    }    return 0;}int max_flow(int s, int t) // s到t最大流{    int flow = 0;    for(;;)    {        bfs(s);        if (level[t] < 0) return flow;        memset(iter,0,sizeof(iter));        int f;        while((f = dfs(s,t,INF)) > 0) { flow += f;}    }}int num[maxn];int main(){#ifdef LOCALfreopen("C:\\Users\\lanjiaming\\Desktop\\acm\\in.txt","r",stdin);//freopen("output.txt","w",stdout);#endifios_base::sync_with_stdio(0);    int T,n,m,kase = 0;    cin>>T;    while(T--)    {        cin>>n>>m;        int s = 0, t = n+m+1;        for(int i= 0; i <= n+m+1; i++) G[i].clear();       int k;       cin>>k;       memset(num,0,sizeof(num));       while(k--)       {           int x;           cin>>x;           num[x]++;       }       for(int i = 1; i <= m; i++) add_edge(s,i,num[i]);       for(int i = 1; i < n; i++)       {           memset(num,0,sizeof(num));           cin>>k;           while(k--)            {                int x;                cin>>x;                num[x]++;            }           for(int j = 1; j <= m; j++)           {               if (num[j] >= 2) add_edge(m+i,j,num[j]-1);               else if(num[j] == 0)  add_edge(j,m+i,1);           }       }       for(int i = 1; i <= m; i++) add_edge(i,t,1);       cout<<"Case #"<<++kase<<": ";       cout<<max_flow(s,t)<<endl;    }    return 0;}


0 0