1. 程式人生 > >洛谷 P2765 魔術球問題 (網路流24題)

洛谷 P2765 魔術球問題 (網路流24題)

題目:魔術球問題

思路: 聽說這題答案的範圍很小。 聽說從1開始列舉答案大小不會超時。 然後我就列舉答案了。 假設答案為m,就對於m個數,每個數暴力的尋找可以可以放在它下面的數再建邊。 由於只有可能上面的點指向下面的點,所以這張圖不存在環,可見是一張二分圖。 然後從m開始跑一遍匈牙利演算法看看能否求出增廣路,如果不能,則說明無法對m進行匹配,則需要再加一根柱子放m。 當柱子的數量大於n時,就說明m-1即為答案。 然後順著match陣列找路徑就好了。

程式碼:

#include<bits/stdc++.h>
using namespace std;

#define maxn 55
#define
maxm 2000
#define m maxm #define read(x) scanf("%d",&x) int n; bool isq[maxm*maxm+5]; vector<int> a[maxm+5]; bool use[maxm+5]; int match[maxm+5]; void init() { for(int i=1;i<=m;i++) { isq[i*i]=true; } } void add(int x) { for(int i=1;i<x;i++) { if(isq[i+x]) a[x].push_back(i);
} } bool dfs(int x) { if(use[x]) return false; use[x]=true; for(int i=0;i<a[x].size();i++) { int y=a[x][i]; if(!match[y]||dfs(match[y])) { match[y]=x; return true; } } return false; } void print(int x) { while(x) { printf("%d ",x); use[x]=true; x=match[x]; } printf("\n"
); } int main() { read(n); init(); int nxt=0; for(int i=0;i<=n;i++) { for(int j=nxt+1;j<=m;j++) { add(j); if(!dfs(j)) { nxt=j; break; } memset(use,0,sizeof(use)); } } nxt--; printf("%d\n",nxt); for(int i=1;i<=nxt;i++) { if(use[i]) continue; print(i); } return 0; }