链接:https://ac.nowcoder.com/acm/contest/1083/D
来源:牛客网
有一个草原可以用一个1~400的数轴表示。有n头羊和q个查询。每头羊的编号分别是1,2,3…n。第i头羊只喜爱数轴上[ai,bi]这样的一个闭区间,每一时刻每头羊只可能在自己喜爱的区间的某个点上吃草。现在给出q个查询,每个查询两个整数l,r。你需要计算出在同一时刻,最多能有多少头羊同时在这个区间内吃草。数轴上每一个整点同一时刻只能容纳一只羊,羊只会在整点吃草。
第一行三个数n q。
第二行n个数a1 a2…an。
第三行n个数b1 b2…bn。
接下来q行每行两个数l,r。表示询问的区间。
输入:
5 3 1 1 1 2 4 1 1 1 3 5 1 5 2 5 1 3
输出:
3 2 2
思路:
设坐标轴的整点1...400属于集合A,羊1...n属于集合B,对于编号为i的羊喜欢的区间a[i],b[i],我们在集合B的i点和集合A中的a[i]...b[i]的点之间连一条边,可以发现这样的图是一张二分图。于是对于每次查询l,r,我们枚举集合A中l...r之间的所有点,求出其最大匹配集合。可以用匈牙利算法或足够优秀的最大流。【比较懒,直接搬的题解QAQ】
以下是我匈牙利算法的代码:
#include<bits/stdc++.h> using namespace std; const int maxn=510; int a[maxn]; int b[maxn]; int match[maxn]; int book[maxn]; int G[maxn][maxn]; int l,r; int dfs(int u){ // 模板 for(int i=l;i<=r;i++){ if(book[i]==0&&G[u][i]==1){ book[i]=1; if(match[i]==0||dfs(match[i])){ match[i]=u; // match[u]=i; return 1; } } } return 0; } int main(){ int n,Q; cin>>n>>Q; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&b[i]); while(Q--){ memset(G,0,sizeof(G)); scanf("%d%d",&l,&r); for(int i=1;i<=n;i++){ if(a[i]>=l&&b[i]<=r){ for(int j=a[i];j<=b[i];j++){ G[i][j]=1; } }else if(a[i]<=r&&b[i]>=r){ for(int j=l;j<=r;j++){ G[i][j]=1; } }else if(a[i]<=l&&b[i]<=r){ for(int j=l;j<=b[i];j++){ G[i][j]=1; } }else if(a[i]>=l&&b[i]>=r){ for(int j=a[i];j<=r;j++){ G[i][j]=1; } } } int ans=0; memset(match,0,sizeof(match)); for(int i=1;i<=n;i++){ memset(book,0,sizeof(book)); if(dfs(i)) ans++; } printf("%d ",ans); } return 0; }
D | 羊吃草 |