标签:double input first end following pre efi complete print
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 24081 | Accepted: 10695 |
Description
Input
Output
Sample Input
5 5 2 2 5 3 2 3 4 2 1 5 3 1 2 5 1 2
Sample Output
4
题目链接:POJ 1274
今天用做了这两道题才知道用最大流解决二分匹配的正确姿势 :首先不要一开始就往S、T这两个点里加边,因为很可能一个点会多次与S相连,那这样这个点总的流量就不是1了。
假设二分图的左半部分是集合$L_i$、右半部分是集合$R_i$,那么首先从$L_i$到$R_i$连一条边,然后将$L_i$与$R_i$记录到各自的数字里,然后各自去重,再从S到去重后的左集合均连一条容量为1的边,从右集合$R_i$中连向T也是一条容量为1的边,然后再跑最大流,代码是POJ的题目代码,HDU的把左边也去重就好了。
代码:
#include <stdio.h> #include <iostream> #include <algorithm> #include <cstdlib> #include <sstream> #include <cstring> #include <bitset> #include <string> #include <deque> #include <stack> #include <cmath> #include <queue> #include <set> #include <map> using namespace std; #define INF 0x3f3f3f3f #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define LC(x) (x<<1) #define RC(x) ((x<<1)+1) #define MID(x,y) ((x+y)>>1) typedef pair<int,int> pii; typedef long long LL; const double PI=acos(-1.0); const int N=210<<1; const int M=N*N*2; struct edge { int to,nxt; int cap; }; edge E[M]; int head[N],tot; int d[N]; vector<int>stall; void init() { CLR(head,-1); tot=0; stall.clear(); } void add(int s,int t,int c) { E[tot].to=t; E[tot].cap=c; E[tot].nxt=head[s]; head[s]=tot++; E[tot].to=s; E[tot].cap=0; E[tot].nxt=head[t]; head[t]=tot++; } int bfs(int s,int t) { CLR(d,INF); d[s]=0; queue<int>Q; Q.push(s); while (!Q.empty()) { int now=Q.front(); Q.pop(); for (int i=head[now]; ~i; i=E[i].nxt) { int v=E[i].to; if(d[v]==INF&&E[i].cap) { d[v]=d[now]+1; if(v==t) return 1; Q.push(v); } } } return d[t]!=INF; } int dfs(int s,int t,int f) { if(s==t||!f) return f; int ret=0; for (int i=head[s]; ~i; i=E[i].nxt) { int v=E[i].to; if(d[v]==d[s]+1&&E[i].cap>0) { int d=dfs(v,t,min(f,E[i].cap)); if(d>0) { E[i].cap-=d; E[i^1].cap+=d; f-=d; ret+=d; if(!f) break; } } } if(!ret) d[s]=-1; return ret; } int dinic(int s,int t) { int ret=0; while (bfs(s,t)) ret+=dfs(s,t,INF); return ret; } int main(void) { int n,m,b,k,i; while (~scanf("%d%d",&n,&m)) { init(); int S=0,T=n+m+1; for (i=1; i<=n; ++i) { scanf("%d",&k); add(S,i,1); while (k--) { scanf("%d",&b); add(i,n+b,1); stall.push_back(b); } } sort(stall.begin(),stall.end()); stall.erase(unique(stall.begin(),stall.end()),stall.end()); int R=stall.size(); for (i=0; i<R; ++i) add(n+stall[i],T,1); printf("%d\n",dinic(S,T)); } return 0; }
POJ 1274 The Perfect Stall、HDU 2063 过山车(最大流做二分匹配)
标签:double input first end following pre efi complete print
原文地址:http://www.cnblogs.com/Blackops/p/6158513.html