This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub beet-aizu/library
// verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2370 #include <bits/stdc++.h> using namespace std; #define call_from_test #include "../../graph/bipartitedecomposition.cpp" #include "../../algorithm/partialsum.cpp" #undef call_from_test signed main(){ cin.tie(0); ios::sync_with_stdio(0); int n,m; cin>>n>>m; BipartiteDecomposition G(n); for(int i=0;i<m;i++){ int u,v; cin>>u>>v; u--;v--; G.add_edge(u,v); } auto res=G.build(); if(res.empty()){ cout<<-1<<endl; return 0; } int offset=0; vector<int> vs; for(auto[x,y]:res){ offset+=min(x,y); vs.emplace_back(abs(x-y)); } auto dp=partial_sum<100000>(vs); long long ans=0; for(int i=0;i<=n;i++){ if(!dp[i]) continue; long long part=offset+i; ans=max(ans,part*(n-part)-m); } cout<<ans<<endl; return 0; }
#line 1 "test/aoj/2370.test.cpp" // verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2370 #include <bits/stdc++.h> using namespace std; #define call_from_test #line 1 "graph/bipartitedecomposition.cpp" #line 3 "graph/bipartitedecomposition.cpp" using namespace std; #endif //BEGIN CUT HERE // O(n) struct BipartiteDecomposition{ vector<vector<int>> G; BipartiteDecomposition(int n):G(n){} void add_edge(int u,int v){ G[u].emplace_back(v); G[v].emplace_back(u); } vector<pair<int, int>> build(){ vector<pair<int, int>> res; vector<int> used(G.size(),-1); for(int i=0;i<(int)G.size();i++){ if(~used[i]) continue; queue<int> que; used[i]=0; que.emplace(i); pair<int, int> cnt; while(!que.empty()){ int v=que.front();que.pop(); if(used[v]==0) cnt.first++; else cnt.second++; for(int u:G[v]){ if(~used[u]){ if(used[u]==used[v]) return {}; continue; } used[u]=used[v]^1; que.emplace(u); } } res.emplace_back(cnt); } return res; } }; //END CUT HERE #ifndef call_from_test int main(){ return 0; } #endif #line 1 "algorithm/partialsum.cpp" #line 3 "algorithm/partialsum.cpp" using namespace std; #endif //BEGIN CUT HERE // O(n sqrt(n) / w) // w: wordsize template<size_t N> bitset<N+1> partial_sum(vector<int> vs){ int sum=0; for(int v:vs) sum+=v; assert(sum<=N); vector<int> cnt(sum+1,0); for(int v:vs) cnt[v]++; for(int i=1;i*2<=sum;i++){ int num=(cnt[i]-1)/2; cnt[i]-=num*2; cnt[i*2]+=num; } bitset<N+1> dp; dp[0]=1; for(int i=1;i<=sum;i++) for(int t=0;t<cnt[i];t++) dp|=dp<<i; return dp; } //END CUT HERE #ifndef call_from_test //INSERT ABOVE HERE signed main(){ return 0; } #endif #line 9 "test/aoj/2370.test.cpp" #undef call_from_test signed main(){ cin.tie(0); ios::sync_with_stdio(0); int n,m; cin>>n>>m; BipartiteDecomposition G(n); for(int i=0;i<m;i++){ int u,v; cin>>u>>v; u--;v--; G.add_edge(u,v); } auto res=G.build(); if(res.empty()){ cout<<-1<<endl; return 0; } int offset=0; vector<int> vs; for(auto[x,y]:res){ offset+=min(x,y); vs.emplace_back(abs(x-y)); } auto dp=partial_sum<100000>(vs); long long ans=0; for(int i=0;i<=n;i++){ if(!dp[i]) continue; long long part=offset+i; ans=max(ans,part*(n-part)-m); } cout<<ans<<endl; return 0; }