P2071 座位安排
套路二分图
好像如果座位只有一个,那么就一人对两位,二分图匹配一下即可
但一排有两个位置
那么就倍增作为
把n排看成n*2排,连4条边
然后这题卡匈牙利,就用网络流
网络流记得memset hed为-1!!!!!
代码:
#include<bits/stdc++.h> using namespace std; #define re register #define inf 2147483647 const int N=4005; const int M=500005; struct edge{ int nxt,v,val; }s[M]; int n; int c[N][N]={0}; int ans=0; int S,T; int hed[M]; int dis[M]; int q[M]; int h,t,cnt=-1; int dfs(int u,int ep){ if(u==T) return ep;//找到了,返回 int flow=0,tmp=0; for(int i=hed[u];~i;i=s[i].nxt){ int v=s[i].v; if(dis[v]==dis[u]+1&&s[i].val>0){ tmp=dfs(v,min(s[i].val,ep)); if(!tmp) continue; ep-=tmp,flow+=tmp; s[i].val-=tmp,s[i^1].val+=tmp;//建立反向边 if(!ep) break;//流量不够用?那就别增广了 } } return flow; } bool bfs(){//dinic的bfs预处理 memset(dis,-1,sizeof(dis)); memset(q,0,sizeof(q)); h=1,t=0; q[++t]=S; dis[S]=0; while(h<=t){ int u=q[h]; for(int i=hed[u];~i;i=s[i].nxt){ int v=s[i].v; if(dis[v]!=-1||s[i].val<1) continue; dis[v]=dis[u]+1; q[++t]=v; } h++; } return dis[T]<0?0:1; } void addege(int x,int y,int z){//加边 cnt++; s[cnt].v=y; s[cnt].val=z; s[cnt].nxt=hed[x]; hed[x]=cnt; } int main(){ memset(hed,-1,sizeof(hed)); scanf("%d",&n); for(re int i=1;i<=2*n;i++){ int x,y; scanf("%d%d",&x,&y); addege(i,2*n+2*x-1,1); addege(2*n+2*x-1,i,0); addege(i,2*n+2*x,1); addege(2*n+2*x,i,0); addege(i,2*n+2*y-1,1); addege(2*n+2*y-1,i,0); addege(i,2*n+2*y,1); addege(2*n+2*y,i,0); } for(int i=1;i<=2*n;i++){ addege(0,i,1); addege(i,0,0); } for(int i=2*n+1;i<=4*n;i++){ addege(i,4*n+1,1); addege(4*n+1,i,0); } S=0,T=4*n+1; while(bfs()){ ans+=dfs(S,inf); } printf("%d\n",ans); return 0; }