洛谷 P2756 飞行员配对方案问题
二分图板子题,按读入建边即可。
注意m和n分别代表什么
(话说洛谷数据是真的水。。m*2=n的数据有82分。。我一开始就是这弄错了)
代码(二分图真的难敲,,这里是dinic )
#include<bits/stdc++.h>
using namespace std;
inline void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);x*=f;
}
inline void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar((x%10)^48);
}
inline void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}
#define maxn 1000050
int n,m,s,t,max_flow,tot=1,k;
int head[maxn],dis[maxn],vis[maxn];
struct edge{int to,nxt,w;}e[maxn<<1];
void add(int u,int v,int w) {e[++tot]=(edge){v,head[u],w},head[u]=tot;}
void ins(int u,int v,int w) {add(u,v,w),add(v,u,0);}
int bfs() {
memset(vis,0,sizeof vis);
memset(dis,63,sizeof dis);//write(dis[0]);
queue<int > q;q.push(s);vis[s]=1;dis[s]=0;
while(!q.empty()) {
int now=q.front();q.pop();vis[now]=0;
for(int i=head[now];i;i=e[i].nxt)
if(e[i].w>0&&dis[e[i].to]>dis[now]+1) {
dis[e[i].to]=dis[now]+1;
if(!vis[e[i].to]) vis[e[i].to]=1,q.push(e[i].to);
}
}return dis[t]<1e9;
}
int dfs(int u,int flow) {
if(u==t) return flow;
for(int i=head[u];i;i=e[i].nxt)
if(e[i].w>0&&dis[e[i].to]==dis[u]+1) {
int f=dfs(e[i].to,min(flow,e[i].w));
if(f>0) {e[i].w-=f,e[i^1].w+=f;return f;}
}
dis[u]=-1;return 0;
}
int dinic() {
max_flow=0;
while(bfs()) {
int flow;
while((flow=dfs(s,1e9))) max_flow+=flow;
}return max_flow;
}
int main() {
read(m),read(n);s=0,t=n+1;
int x,y;
while(1) {
read(x),read(y);if(x<0) break;
ins(x,y,1);
}
for(int i=1;i<=m;i++) ins(s,i,1);
for(int i=m+1;i<=n;i++) ins(i,t,1);
dinic();write(max_flow);
for(int i=1;i<=m;i++) {
for(int j=head[i];j;j=e[j].nxt)
if(e[j].to!=s&&(!(j&1))) if(!e[j].w) printf("%d %d\n",i,e[j].to);
}
return 0;
}