POJ2584 T-Shirt Gumbo 二分图匹配(网络流)

时间:2024-05-17 22:07:26
 #include <cstdio>
 #include <cstring>
 #include <algorithm>

 const int inf=0x3f3f3f3f;
 ;

 struct Edge
 {
     int to;
     int next;
     int capacity;

     void assign(int t,int n,int c)
     {
         to=t; next=n; capacity=c;
     }
 };

 Edge edgeList[];
 ];
 ;

 inline void init()
 {
     edgeCnt=;
     memset(head,-,sizeof(head));
 }

 ];
 int X;

 inline int idx(char s)
 {
     switch(s)
     {
     ;
     ;
     ;
     ;
     ;
     ;
     }
 }

 inline void addEdge(int v1,int v2,int c)
 {
     edgeList[edgeCnt].assign(v2,head[v1],c);
     head[v1]=edgeCnt++;
     edgeList[edgeCnt].assign(v1,head[v2],);
     head[v2]=edgeCnt++;
 }

 bool input()
 {
     scanf("%s",cmd);
     ]=='E') return false;

     scanf("%d",&X);
     ;i<=X+;i++)
     {
         scanf("%s",cmd);
         ]);
         ]);
         for(int j=sm;j<=lg;j++) addEdge(j,i,inf);
         addEdge(i,sink,);
     }
     ;i<=;i++)
     {
         int n; scanf("%d",&n);
         addEdge(,i,n);
     }
     scanf("%s",cmd);
     return true;
 }

 ];

 #include <queue>

 int bfs()
 {
     memset(dist,,sizeof(dist));
     dist[]=;

     std::queue<int> __bfs;
     __bfs.push();

     while(!__bfs.empty())
     {
         int cur=__bfs.front();
         __bfs.pop();

         ;e=edgeList[e].next)
         {
             int __to=edgeList[e].to;
             if(edgeList[e].capacity && !dist[__to])
             {
                 dist[__to]=dist[cur]+;
                 __bfs.push(__to);
             }
         }
     }
     return dist[sink];
 }

 int dinic_aux(int cur,int flow)
 {
     if(cur==sink) return flow;

     ;
     ;
     ;e=edgeList[e].next)
     {
         int __to=edgeList[e].to;
          && edgeList[e].capacity)
         {
             temp=dinic_aux(__to,std::min(flow,edgeList[e].capacity));
             res+=temp;
             flow-=temp;
             edgeList[e].capacity-=temp;
             edgeList[e^].capacity+=temp;
         }
     }
     return res;
 }

 inline int dinic()
 {
     ;
     ,inf);
     return res;
 }

 const char success[]="T-shirts rock!";
 const char fail[]="I'd rather not wear a shirt anyway...";

 inline void solve()
 {
     bool proc=true;
     while(proc)
     {
         init();
         proc=input();
         if(proc) printf("%s\n",dinic()==X?success:fail);
     }
 }

 ; }

Using Dinic Algorithm

这道题有两种解决思路:

(1)拆点。将n件同样尺码的T恤拆成n个节点,然后对于每一个分离的节点向对应的人连边

  效率比较低,点的个数最大有可能达到100以上

(2)网络流。建模的基本思想与一般二分图匹配的网络流建模相同,只是从源点向T恤尺码代表的节点连边时,载量设为该种T恤的件数

  点的个数不超过30,相对比较高效

Appendix:二分图匹配的网络流建模:

约定二分图的两部分记作A和B

设立一个源点和汇点。源点同A中所有点连边,载量设为1(表示该点只能在匹配中被选中一次);汇点同B中所有点连边,载量也设为1

二分图中原来的边保留,令其方向为A→B,载量为任意正整数

对于网络流问题,边表是个很不错的选择。既能像邻接表那样节约空间,又能方便地记录反向边。

记正向边的标号为2x,那么反向边的标号就是2x+1,访问反向边只需将正向边的标号xor 1