(二分图)洛谷P2071座位安排

it2025-05-29  11

洛谷P2071座位安排

思路:

网络流难在建图上面。 这题(应该也可以,我没尝试过)用二分图匹配去跑。可以拆点,将一排的座位拆成两个点,一个 i i i,一个 i + n i+n i+n,然后匈牙利算法跑。 也可以用网络流跑最大流,将 S S S向每个人 i i i连一条流量为 1 1 1的边,再将每个人向他想坐的位置连一条流量为 1 1 1的边,至于每排座位可以坐两个人,可以将每排座位向 T T T连一条流量为 2 2 2的边,这样就可以让他的最大流量是 2 2 2了。

代码:

#include<bits/stdc++.h> #define pii pair<int,int> #define int long long #define cl(x,y) memset(x,y,sizeof(x)) #define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n"; const int N=5e5+210; const int mod=1e9+7; const int maxn=0x3f3f3f3f; const int minn=0xc0c0c0c0; const int inf=99999999; using namespace std; struct edge { int u,v,w; }maze[N<<1]; int len=1,head[N]={0}; int dep[N];//深度 void add(int u,int v,int w) { maze[++len]={head[u],v,w}; head[u]=len; } int dfs(int u,int f,int t) { int ans=0,i; if(u==t) return f; for(i=head[u];i && f;i=maze[i].u) { int v=maze[i].v,w=maze[i].w; if(dep[v]==dep[u]+1 && w)//符合深度关系且能流 { int sum=dfs(v,min(f,w),t); maze[i].w-=sum; maze[i^1].w+=sum; f-=sum; ans+=sum; } } if(!ans) dep[u]=-2; return ans; } int bfs(int s,int t) { queue<int> q; cl(dep,0); dep[s]=1;//源点深度为1 q.push(s); while(!q.empty()) { int u=q.front(),i; q.pop(); for(i=head[u];i;i=maze[i].u) { int v=maze[i].v,w=maze[i].w; if(w && !dep[v])//有深度且能流 { dep[v]=dep[u]+1; q.push(v); } } } return dep[t]; } int dinic(int s,int t) { int ans=0; while(bfs(s,t)) ans+=dfs(s,maxn,t); return ans; } signed main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int n,i; cin>>n; int s=0,t=3*n+1; for(i=1;i<=2*n;i++) { int x,y; cin>>x>>y; add(s,i,1); add(i,s,0); add(i,x+2*n,1); add(x+2*n,i,0); add(i,y+2*n,1); add(y+2*n,i,0); } for(i=1;i<=n;i++) { add(i+2*n,t,2); add(t,i+2*n,0); } cout<<dinic(s,t)<<endl; return 0; }
最新回复(0)