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

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4
  5 const int inf=0x3f3f3f3f;
  6 const int sink=30;
  7
  8 struct Edge
  9 {
 10     int to;
 11     int next;
 12     int capacity;
 13
 14     void assign(int t,int n,int c)
 15     {
 16         to=t; next=n; capacity=c;
 17     }
 18 };
 19
 20 Edge edgeList[2048];
 21 int head[40];
 22 int edgeCnt=0;
 23
 24 inline void init()
 25 {
 26     edgeCnt=0;
 27     memset(head,-1,sizeof(head));
 28 }
 29
 30 char cmd[20];
 31 int X;
 32
 33 inline int idx(char s)
 34 {
 35     switch(s)
 36     {
 37     case ‘S‘: return 1;
 38     case ‘M‘: return 2;
 39     case ‘L‘: return 3;
 40     case ‘X‘: return 4;
 41     case ‘T‘: return 5;
 42     default : return -1;
 43     }
 44 }
 45
 46 inline void addEdge(int v1,int v2,int c)
 47 {
 48     edgeList[edgeCnt].assign(v2,head[v1],c);
 49     head[v1]=edgeCnt++;
 50     edgeList[edgeCnt].assign(v1,head[v2],0);
 51     head[v2]=edgeCnt++;
 52 }
 53
 54 bool input()
 55 {
 56     scanf("%s",cmd);
 57     if(cmd[0]==‘E‘) return false;
 58
 59     scanf("%d",&X);
 60     for(int i=6;i<=X+5;i++)
 61     {
 62         scanf("%s",cmd);
 63         int sm=idx(cmd[0]);
 64         int lg=idx(cmd[1]);
 65         for(int j=sm;j<=lg;j++) addEdge(j,i,inf);
 66         addEdge(i,sink,1);
 67     }
 68     for(int i=1;i<=5;i++)
 69     {
 70         int n; scanf("%d",&n);
 71         addEdge(0,i,n);
 72     }
 73     scanf("%s",cmd);
 74     return true;
 75 }
 76
 77 int dist[40];
 78
 79 #include <queue>
 80
 81 int bfs()
 82 {
 83     memset(dist,0,sizeof(dist));
 84     dist[0]=1;
 85
 86     std::queue<int> __bfs;
 87     __bfs.push(0);
 88
 89     while(!__bfs.empty())
 90     {
 91         int cur=__bfs.front();
 92         __bfs.pop();
 93
 94         for(int e=head[cur];e>-1;e=edgeList[e].next)
 95         {
 96             int __to=edgeList[e].to;
 97             if(edgeList[e].capacity && !dist[__to])
 98             {
 99                 dist[__to]=dist[cur]+1;
100                 __bfs.push(__to);
101             }
102         }
103     }
104     return dist[sink];
105 }
106
107 int dinic_aux(int cur,int flow)
108 {
109     if(cur==sink) return flow;
110
111     int res=0;
112     int temp=0;
113     for(int e=head[cur];e>-1;e=edgeList[e].next)
114     {
115         int __to=edgeList[e].to;
116         if(dist[__to]==dist[cur]+1 && edgeList[e].capacity)
117         {
118             temp=dinic_aux(__to,std::min(flow,edgeList[e].capacity));
119             res+=temp;
120             flow-=temp;
121             edgeList[e].capacity-=temp;
122             edgeList[e^1].capacity+=temp;
123         }
124     }
125     return res;
126 }
127
128 inline int dinic()
129 {
130     int res=0;
131     while(bfs()) res+=dinic_aux(0,inf);
132     return res;
133 }
134
135 const char success[]="T-shirts rock!";
136 const char fail[]="I‘d rather not wear a shirt anyway...";
137
138 inline void solve()
139 {
140     bool proc=true;
141     while(proc)
142     {
143         init();
144         proc=input();
145         if(proc) printf("%s\n",dinic()==X?success:fail);
146     }
147 }
148
149 int main() { solve(); return 0; }

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

时间: 2024-10-12 13:53:07

POJ2584 T-Shirt Gumbo 二分图匹配(网络流)的相关文章

cogs_396_魔术球问题_(最小路径覆盖+二分图匹配,网络流24题#4)

描述 http://cojs.tk/cogs/problem/problem.php?pid=396 连续从1开始编号的球,按照顺寻一个个放在n个柱子上,\(i\)放在\(j\)上面的必要条件是\(i+j\)是一个完全平方数.问做多能放到几号球. 分析 cogs是简化版,我在网上找了个完整版的测试数据,要求输出方案... 求最大放几号球不方便,我们考虑枚举最大的球号,计算最少需要多少柱子. 我们对于满足\(j<i\)且\(i+j\)是一个完全平方数的\(i,j\),从\(j\)向\(i\)连一条

BZOJ 1191: [HNOI2006]超级英雄Hero(二分图匹配)

云神说他二分图匹配从来都是用网络流水过去的...我要发扬他的精神.. 这道题明显是二分图匹配.网络流的话可以二分答案+最大流.虽然跑得很慢.... ---------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostrea

cogs_14_搭配飞行员_(二分图匹配+最大流,网络流24题#01)

描述 http://cojs.tk/cogs/problem/problem.php?pid=14 有一些正飞行员和副飞行员,给出每个正飞行员可以和哪些副飞行员一起飞.一架飞机上必须一正一副,求最多多少飞机可以飞. 分析 裸的二分图匹配... 请叫我水题小王子... 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=100+5,INF=0x7fffffff; 5 int n,m,cnt=1; 6 int l

POJ3189_Steady Cow Assignment(二分图多重匹配/网络流)

解题报告 http://blog.csdn.net/juncoder/article/details/38340447 题目传送门 题意: B个猪圈,N头猪,每头猪对每个猪圈有一个满意值,要求安排这些猪使得最大满意和最小满意的猪差值最小 思路: 二分图的多重匹配问题; 猪圈和源点连边,容量为猪圈容量,猪与汇点连边,容量1; 猪圈和猪之间连线取决所取的满意值范围; 二分查找满意值最小差值的范围. #include <iostream> #include <cstring> #incl

【wikioi】1922 骑士共存问题(网络流/二分图匹配)

用匈牙利tle啊喂?和网络流不都是n^3的吗.... (更新:what!!!!!!发现个无语的问题,.!!!!结构比数组快啊orz,这节奏不对啊....以后图都写结构的节奏啊... #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> using namespace

培训补坑(day4:网络流建模与二分图匹配)

补坑时间到QAQ 好吧今天讲的是网络流建模与二分图匹配... day3的网络流建模好像说的差不多了.(囧) 那就接着补点吧.. 既然昨天讲了建图思想,那今天就讲讲网络流最重要的技巧:拆点. 拆点,顾名思义,就是把一个状态拆成数个点以满足题目要求. 今天主要围绕一个例题来讲:修车.(虽然是丧题,但是却是网络流算法思想实现的典例) ------------------我是分割线------------------ 题目: 同一时刻有位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不

【BZOJ4554】游戏(二分图匹配,网络流)

[BZOJ4554]游戏(二分图匹配,网络流) 题解 Description 在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂.简单的说,这个游戏就是在一张地图上放上若干个炸弹,看 是否能炸到对手,或者躲开对手的炸弹.在玩游戏的过程中,小H想到了这样一个问题:当给定一张地图,在这张 地图上最多能放上多少个炸弹能使得任意两个炸弹之间不会互相炸到.炸弹能炸到的范围是该炸弹所在的一行和一 列,炸弹的威力可以穿透软石头,但是不能穿透硬石头.给定一张nm的网格地图:其中代表空地,炸弹的威力可 以穿透,可

11082 - Matrix Decompressing (网络流建模|二分图匹配)

该题是一道经典的二分图匹配的题目 .现在终于有点明白什么是二分图匹配了,其实说白了就是依赖于最大流算法之上的一种解决特定问题的算法 . 所谓二分图,就是我们假定有两个集合A和B,每个集合中有若干元素(点),其中源点与A相连,汇点与B相连,并且他们的总容量决定了最终答案的上限,所以一定要维护好 . 然后由A中的点向B中的点连线,他们之间也有一定的容量制约关系(具体看题目中的边权值限制).这样就可以求出最大流量匹配了. 有时我们要求完美匹配,即所有流入的量等于流出的量  . 该题构思极其巧妙,因为我

网络流24题 第一题 - 洛谷2756 飞行员配对方案 二分图匹配 匈牙利算法

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 题意概括 裸的二分图匹配 题解 匈牙利算法 上板子 代码 #include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; const int N=100+5; int m,n,a,b,match[N