链接
http://acm.hdu.edu.cn/showproblem.php?pid=5943
题解
首先,在区间重叠部分的那些人肯定就呆在原地(假设他们不呆在原地,可以证明其它所有可行方案经过一定的变换总可以得到一种他们呆在原地的可行方案)
然后题目所给范围内相邻的约数的差不会超过
500
500
500,所以只要去掉重叠部分的区间的长度大于
500
500
500就直接输出无解,否则建二分图暴力匹配
代码
#include <bits/stdc++.h>
#define maxn 1010
#define maxe 250010
using namespace std;
struct Graph
{
int etot, head[maxn], to[maxe], next[maxe], w[maxe];
void clear(int N)
{
for(int i=1;i<=N;i++)head[i]=0;
etot=0;
}
void adde(int a, int b, int c=0){to[++etot]=b;w[etot]=c;next[etot]=head[a];head[a]=etot;}
}G;
struct Hungarian
{
bool in[maxn];
int link[maxn];
bool dfs(Graph &G, int x)
{
int p, t;
for(p=G.head[x];p;p=G.next[p])
{
if(!in[t=G.to[p]])
{
in[t]=true;
if(link[t]==0||dfs(G,link[t]))
{
link[t]=x;
return true;
}
}
}
return false;
}
int run(Graph &G, int n1, int n2)
{
int ans=0, i, j;
for(i=1;i<=n1+n2;i++)link[i]=0;
for(i=1;i<=n1;i++)
{
for(j=n1+1;j<=n1+n2;j++)in[j]=false;
ans+=dfs(G,i);
}
return ans;
}
}hun;
int main()
{
int T, N, S, kase, i, j, n;
cin>>T;
for(kase=1;kase<=T;kase++)
{
cout<<"Case #"<<kase<<": ";
cin>>N>>S;
if(S==0)
{
cout<<"Yes"<<endl;
continue;
}
if(min(N,S)>500)
{
cout<<"No"<<endl;
continue;
}
n=min(N,S);
G.clear(n);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if((j+max(S,N))%i==0)G.adde(i,n+j);
if(hun.run(G,n,n)==n)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}