题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5943
题意:n
个人编号为[s+1,s+n]
,有n
个座位编号为[1,n]
,编号为i
的人只能坐到编号为它的约数的座位,问每个人是否都有位置坐。
首先,可以肯定的是素数编号的人只能做到自己的编号上或者是1上,那么假如[s+1,s+n]区间内出现了两个以上的素数,那么整个情况是无解的。
其次,假如s<n的话,可以把[s+1,s+n]直接放到[s+1,s+n]上,剩下的将会是s个人和s个座位,人的编号是[n+1,n+s],座位的编号是[s+1,s+n],所以直接给s和n交换一下就行。
我断定1000个数之间一定会出现至少两个素数,因此当n>1000的时候就是无解了。
接下来就是O(n^2),按照能否整除建图了,跑出最大匹配,看看跟n是不是相等就行了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 1010; 5 int nu, nv; 6 int G[maxn][maxn]; 7 int linker[maxn]; 8 bool vis[maxn]; 9 int s, n; 10 11 bool dfs(int u) { 12 for(int v = 1; v <= nv; v++) { 13 if(G[u][v] && !vis[v]) { 14 vis[v] = 1; 15 if(linker[v] == -1 || dfs(linker[v])) { 16 linker[v] = u; 17 return 1; 18 } 19 } 20 } 21 return 0; 22 } 23 24 int hungary() { 25 int ret = 0; 26 memset(linker, -1, sizeof(linker)); 27 for(int u = 1; u <= nu; u++) { 28 memset(vis, 0, sizeof(vis)); 29 if(dfs(u)) ret++; 30 } 31 return ret; 32 } 33 34 int main() { 35 // freopen("in", "r", stdin); 36 int T, _ = 1; 37 scanf("%d", &T); 38 while(T--) { 39 scanf("%d %d", &s, &n); 40 memset(G, 0, sizeof(G)); 41 printf("Case #%d: ", _++); 42 if(s < n) swap(s, n); 43 if(n > 1000) { 44 puts("No"); 45 continue; 46 } 47 nu = 2 * n, nv = n; 48 for(int i = 1; i <= n; i++) { 49 for(int j = 1; j <= n; j++) { 50 if((s + i) % j == 0) G[i+n][j] = 1; 51 } 52 } 53 if(hungary() == n) puts("Yes"); 54 else puts("No"); 55 } 56 return 0; 57 }
时间: 2024-10-01 03:31:05