計蒜客 17417 Highest Tower(思維+圖論)
阿新 • • 發佈:2017-10-08
sca 選擇 blog 基於 一個點 oid ons ++ i++
題解:
實際上一個可行解即選取長和寬的一個,使得最後每一組選第一維的數值都不同
在此基礎上,使得另一維的和最大。
然後建立圖論模型
對於每一個方塊,在a和b之間連邊。
對於選擇的方案,如果選擇a->b,那麽就是以a為底,b為高
所以最後的圖一定要滿足所有點的出度為1(出度為2就有重復了)
基於這個我們發現只有兩種情況。
1、圖中含有環,實際上所有邊的方向都是固定的,答案就是每個點的入度*每個點的值加起來。
2、圖中不含環(樹的結構),那麽實際上可以選取一個點為根,根的答案可以額外計算。所以就選取樹中值最大的那個點為根即可。
#include <iostream> #include<cstring> #include <cstdio> #include <vector> #include <map> using namespace std; const int maxn = 5e5 + 100; vector<int> G[maxn]; map<int, int> M; long long m, N, Max, ans; int vis[maxn], v[maxn]; void dfs(int x){ if(vis[x]) return; vis[x] = 1; m += G[x].size(); N++; Max = max(Max, (longlong)v[x]); ans += (G[x].size()-1)*v[x]; for(auto to : G[x]) dfs(to); } int n, x, y, tot; int main() { scanf("%d", &n); for(int i = 1; i <= n; i++){ scanf("%d %d", &x, &y); if(!M[x]){ M[x] = ++tot; v[tot] = x; }if(!M[y]){ M[y] = ++tot; v[tot] = y; } G[M[x]].push_back(M[y]); G[M[y]].push_back(M[x]); } memset(vis, 0, sizeof(vis)); for(int i = 1; i <= tot; i++){ if(!vis[i]) { N = 0; m = 0; Max = 0; dfs(i); if(m/2 == N-1) ans += Max; } } cout<<ans<<endl; return 0; }
計蒜客 17417 Highest Tower(思維+圖論)