TopCoder SRM621 DIV1 MEDIUM (500pt)
Problem Statement
ノード数 $N$ の無向グラフが $2$ 個,$G_1,G_2$ が与えられる.
ノードは,それぞれのグラフで,$0,1,\ldots,N-1$ の番号が付けられている.
グラフ $G_1$ の枝 $e_1$ と,グラフ $G_2$ の枝 $e_2$ に対して $S(e_1,e_2)$ を次のように定める.
グラフ $G_k$ から枝 $e_k$ を取り除くと $2$ つの連結グラフに分かれるが,それをグラフ $X_k,Y_k$ とする($k=1,2$).
$X_1,X_2$ に両方含まれているノード番号,$X_1,Y_2$ に両方含まれているノード番号,$Y_1,X_2$ に両方含まれているノード番号,$Y_1,Y_2$ に両方含まれているノード番号,の $4$ つのうちで最も大きい数を $S(e_1,e_2)$ とする.
全ての枝のペア $(e_1,e_2)$ に対する $S(e_1,e_2)$ の自乗和
$\displaystyle \sum_{(e_1,e_2)} S(e_1,e_2)^2$
を求める問題.
要するに $S(e_1,e_2)$ を全部計算すれば良い.
まず,グラフ $G_1$ において,どの枝を取り除くパターン $N-1$ 通りは愚直に全部行う.
その際,DFSなどで片方の連結グラフ $X_1$ に含まれるノードを列挙して,$O(1)$ で判定できるようにしておく.また,$X_1$ に含まれるノード数も計算しておく.
グラフ $G_2$ においては,根付き木と考える.
各ノードについて,自分と自分の子供以下のノードのなかで,$X_1$ に含まれるノード番号のノードがいくつあるか,含まれないノードがいくつあるかを葉の方から順番に計算していく.
すると,各ノードについて,自分とその親をつなぐ枝を $e_2$ として取り除く場合の $S(e_1,e_2)$ は $O(1)$ で計算できるようになる.
合計で時間計算量 $O(N^2)$.
#include<bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)
#define ll long long
int N;
int edge1[4100][4100], es1[4100];
int edge2[4100][4100], es2[4100];
ll res;
int del1, del2;
int colored[4100], colored_all;
void dfs1(int now, int bef){
int i, k;
colored[now] = 1;
colored_all++;
rep(i,es1[now]){
k = edge1[now][i];
if(k==bef) continue;
if(now==del1 && k==del2) continue;
if(now==del2 && k==del1) continue;
dfs1(k, now);
}
}
int dp[4100], all[4100];
void dfs2(int now, int bef){
int i, k, mx;
dp[now] = colored[now];
all[now] = 1;
rep(i,es2[now]){
k = edge2[now][i];
if(k==bef) continue;
dfs2(k, now);
dp[now] += dp[k];
all[now] += all[k];
}
if(bef != -1){
mx = max(dp[now], all[now]-dp[now]);
mx = max(mx, colored_all - dp[now]);
mx = max(mx, N - colored_all - all[now] + dp[now]);
res += mx*mx;
}
}
class TreesAnalysis {
public:
ll treeSimilarity(vector <int> tree1, vector <int> tree2) {
int i, j, k, d;
N = tree1.size() + 1;
res = 0;
rep(i,N) es1[i] = es2[i] = 0;
rep(i,N-1){
j = tree1[i];
edge1[i][es1[i]++] = j;
edge1[j][es1[j]++] = i;
j = tree2[i];
edge2[i][es2[i]++] = j;
edge2[j][es2[j]++] = i;
}
rep(d,N-1){
rep(i,N) colored[i] = 0; colored_all = 0;
del1 = d;
del2 = tree1[d];
dfs1(0, -1);
dfs2(0, -1);
}
return res;
}
}
Current time: 2024年04月20日15時29分55秒
Last modified: 2014年05月24日04時39分19秒 (by laycrs)
Tags: Competitive_Programming TopCoder Single_Round_Match SRM621 SRM_Div1_Medium
トップページに戻る
Logged in as: unknown user (not login)