結果
問題 | No.317 辺の追加 |
ユーザー |
|
提出日時 | 2015-12-20 11:32:09 |
言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
結果 |
AC
|
実行時間 | 1,403 ms / 2,000 ms |
コード長 | 2,634 bytes |
コンパイル時間 | 926 ms |
コンパイル使用メモリ | 102,520 KB |
実行使用メモリ | 9,472 KB |
最終ジャッジ日時 | 2024-09-17 11:59:06 |
合計ジャッジ時間 | 23,915 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 38 |
ソースコード
#include <cstdio>#include <iostream>#include <sstream>#include <fstream>#include <iomanip>#include <algorithm>#include <cmath>#include <string>#include <vector>#include <list>#include <queue>#include <stack>#include <set>#include <map>#include <bitset>#include <numeric>#include <limits>#include <climits>#include <cfloat>#include <functional>using namespace std;class UnionFindTree{private:int n;vector<int> parent; // 親ノードvector<int> rank; // 木の高さの上限vector<int> num; // グループの要素数int find(int i){if(parent[i] == i)return i;return parent[i] = find(parent[i]);}public:UnionFindTree(int n0){ // コンストラクタn = n0;parent.resize(n);for(int i=0; i<n; ++i)parent[i] = i;rank.assign(n, 0);num.assign(n, 1);}void unite(int a, int b){ // aとbのグループを併合if((a = find(a)) != (b = find(b))){if(rank[a] < rank[b]){parent[a] = b;num[b] += num[a];}else{parent[b] = a;if(rank[a] == rank[b])++ rank[a];num[a] += num[b];}-- n;}}bool same(int a, int b){ // aとbのグループが同じかを調べるreturn find(a) == find(b);}int getNum(){ // グループの数を返すreturn n;}int getNum(int a){ // aのグループの要素数を返すreturn num[find(a)];}};const int INF = INT_MAX / 2;int main(){int n, m;cin >> n >> m;UnionFindTree uft(n);for(int i=0; i<m; ++i){int u, v;cin >> u >> v;uft.unite(u-1, v-1);}vector<int> a(n+1);for(int i=0; i<n; ++i)++ a[uft.getNum(i)];vector<int> dp(n+1, INF);dp[0] = -1;for(int i=1; i<=n; ++i){if(a[i] == 0)continue;a[i] /= i;vector<int> nextDp = dp;for(int j=0; j<i; ++j){multiset<int> ms;for(int k=0; j+k*i<=n; ++k){if(!ms.empty())nextDp[j+k*i] = min(nextDp[j+k*i], *ms.begin() + k);ms.insert(dp[j+k*i] - k);if(k >= a[i])ms.erase(ms.find(dp[j+(k-a[i])*i] - (k - a[i])));}}dp.swap(nextDp);}for(int i=1; i<=n; ++i){if(dp[i] < INF)cout << dp[i] << endl;elsecout << -1 << endl;}return 0;}