洛谷2756飛行員配對方案問題
阿新 • • 發佈:2018-12-26
題目連結:飛行員配對方案問題
很多人把這題當做二分圖匹配的模板做,匈牙利的時間複雜度為\(O(nm)\)
但是如果用dinic去做時間就會是\(O(\sqrt nm)\)
建立超級源點\(s\)和\(t\),直接按照輸入連邊,源點和匯點分別連向一個點集即可
#include<iostream> #include<string> #include<string.h> #include<stdio.h> #include<algorithm> #include<math.h> #include<vector> #include<queue> #include<map> using namespace std; #define maxd 1e9+7 struct network_flows{ struct node{ int from,to,nxt,flow; }sq[100100]; int all,dep[100100],head[100100],cur[100100],n,m,s,t; bool vis[100100]; void init(int n,int m) { this->s=n+m+1;this->t=n+m+2; this->n=n+m+2;this->all=1; memset(head,0,sizeof(head)); } void add(int u,int v,int w) { all++;sq[all].from=u;sq[all].to=v;sq[all].nxt=head[u];sq[all].flow=w;head[u]=all; all++;sq[all].from=v;sq[all].to=u;sq[all].nxt=head[v];sq[all].flow=0;head[v]=all; } bool bfs() { queue<int> q;int i; memset(vis,0,sizeof(vis)); vis[s]=1;q.push(s);dep[s]=0; while (!q.empty()) { int u=q.front();q.pop(); for (i=head[u];i;i=sq[i].nxt) { int v=sq[i].to; if ((!vis[v]) && (sq[i].flow)) { vis[v]=1;dep[v]=dep[u]+1;q.push(v); } } } if (!vis[t]) return 0; for (i=1;i<=n;i++) cur[i]=head[i]; return 1; } int dfs(int now,int to,int lim) { if ((!lim) || (now==to)) return lim; int i,sum=0; for (i=cur[now];i;i=sq[i].nxt) { cur[now]=i;int v=sq[i].to; if (dep[now]+1==dep[v]) { int f=dfs(v,to,min(lim,sq[i].flow)); if (f) { lim-=f;sum+=f; sq[i].flow-=f; sq[i^1].flow+=f; if (!lim) break; } } } return sum; } int work() { int ans=0; while (bfs()) ans+=dfs(s,t,maxd); return ans; } void out(int n,int m) { int i,j; for (i=1;i<=n;i++) { for (j=head[i];j;j=sq[j].nxt) { if ((sq[j].to>n) && (sq[j].to<=n+m) && (!sq[j].flow)) printf("%d %d\n",i,sq[j].to); } } } }dinic; int n,m,s,t; int read() { int x=0,f=1;char ch=getchar(); while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();} while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();} return x*f; } void init() { n=read();m=read();int i,j,u,v; dinic.init(n,m); s=n+m+1;t=n+m+2; for (i=1;i<=n;i++) dinic.add(s,i,1); for (i=1;i<=m;i++) dinic.add(n+i,t,1); while ((scanf("%d%d",&u,&v)) && (u!=-1) && (t!=-1)) dinic.add(u,v,1); } void work() { int ans=dinic.work(); if (!ans) {printf("No Solution!");return;} printf("%d\n",ans); dinic.out(n,m); } int main() { init(); work(); return 0; }