1. 程式人生 > >計蒜客 17417 Highest Tower(思維+圖論)

計蒜客 17417 Highest Tower(思維+圖論)

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, (long
long)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(思維+圖論)