LibreOJ 6000 搭配飞行员(最大流)
题解:最基础的最大流,按照主飞行员与起点建边,副飞行员与终点建边,可以同坐的主副飞行员之间建边,值均为一,然后跑一边最大流就完美了!
代码如下:
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define inf 0x3f3f3f3f using namespace std; int head[10010],next[10010],v[10010],w[10010],deep[10010]; int s,t,cnt; void init() { cnt=-1; memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); } void add(int from,int to,int cost) { cnt++; next[cnt]=head[from]; v[cnt]=to; w[cnt]=cost; head[from]=cnt; } void add_edge(int from,int to,int cost) { add(from,to,cost); add(to,from,0); } int bfs(int s,int t) { queue<int> q; memset(deep,0,sizeof(deep)); deep[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=next[i]) { if(w[i]>0&&(!deep[v[i]])) { deep[v[i]]=deep[u]+1; q.push(v[i]); } } } if(!deep[t]) { return 0; } return 1; } int dfs(int u,int t,int dist) { if(u==t) { return dist; } for(int i=head[u];i!=-1;i=next[i]) { if((deep[v[i]]==deep[u]+1)&&w[i]) { int di=dfs(v[i],t,min(w[i],dist)); if(di>0) { w[i]-=di; w[i^1]+=di; return di; } } } return 0; } int dinic(int s,int t) { int res=0; while(bfs(s,t)) { while(int d=dfs(s,t,inf)) { res+=d; } } return res; } int main() { int n,m; init(); scanf("%d%d",&n,&m); s=0;t=n+1; for(int i=1;i<=m;i++) { add_edge(s,i,1); } for(int i=m+1;i<=n;i++) { add_edge(i,t,1); } int x,y; while(scanf("%d%d",&x,&y)!=EOF) { add_edge(x,y,1); } int ans=dinic(s,t); printf("%d\n",ans); }