标签: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