SRM 578

来源:互联网 发布:程序员笔记本对cpu 编辑:程序博客网 时间:2024/06/01 08:58

先枚举割掉一个边,使得树分成两个树

然后枚举两个树的根,来比较这两个树的最大同构子树大小。

需要加个记忆化:dp[i][ifather][j][jfather],即以ifather为父亲的i节点为根的子树和jfather为父亲j节点为根的子树的最大同构子树的大小


看上去是个4维的,但其实[i][ifather]这两维合法的只有O(n),即边的个数。同理,这个数组合法的其实只有n^2级别个。


比如对于i和j两个节点,处理以他们为根的最大同构树,先枚举他们的孩子分支,即得到一个n*m的矩阵是他们孩子分支最大同构的大小。。

这其实是一个二分图带权最优匹配。

#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <ctime>#include <cstring>#include <queue>using namespace std;class DeerInZooDivOne {public:int getmax(vector<int> , vector<int> );};vector<int> nt[55];int dp[55][55][55][55];/*************************************************/#define N 200#define inf 2000000000#define Min(a,b) (((a)<(b))?a:b)struct edge {int s, t, f, v, next;} e[300 * N];int eid;int node[N];void init() {memset(node, -1, sizeof(node));eid = 0;}void addedge(int s, int t, int f, int v) {e[eid].s = s;e[eid].t = t;e[eid].f = f;e[eid].v = v;e[eid].next = node[s];node[s] = eid++;e[eid].s = t;e[eid].t = s;e[eid].f = 0;e[eid].v = -v;e[eid].next = node[t];node[t] = eid++;}int dist[N], path[N];bool in[N];queue<int> q;int SPFA(int s, int t, int n) {int i, u, v;memset(in, false, sizeof(in));for (i = 0; i < n; ++i)dist[i] = inf;dist[s] = 0;path[s] = -1;q.push(s);in[s] = true;while (!q.empty()) {u = q.front();q.pop();in[u] = false;for (i = node[u]; i != -1; i = e[i].next) {v = e[i].t;if (e[i].f > 0 && dist[u] + e[i].v < dist[v]) {dist[v] = dist[u] + e[i].v;path[v] = i;if (!in[v]) {q.push(v);in[v] = true;}}}}return dist[t] != inf;}void output() {int i;for (i = 0; i < eid; ++i)printf("s:%d t:%d f:%d v:%d next:%d\n", e[i].s, e[i].t, e[i].f, e[i].v,e[i].next);}int max_flow_min_cost(int s, int t, int n) {int i, minf, f = 0, cost = 0;//output();while (SPFA(s, t, n)) {for (i = path[t], minf = e[path[t]].f; i != -1; i = path[e[i].s])minf = Min(minf,e[i].f);f += minf;for (i = path[t]; i != -1; i = path[e[i].s]) {cost += minf * e[i].v;e[i].f -= minf;e[i ^ 1].f += minf;}}return cost;}/*************************************************/int gao2(int n, int m, int graph[][55]) {int i, j;init();int s = n + m;int t = n + m + 1;for (i = 0; i < n; ++i) {addedge(s, i, 1, 0);addedge(i, t, 1, 0);}for (i = 0; i < m; ++i) {addedge(i + n, t, 1, 0);}for (i = 0; i < n; ++i) {for (j = 0; j < m; ++j) {addedge(i, j + n, 1, -graph[i][j]);}}return -max_flow_min_cost(s, t, t + 1);}int gao(int i, int fi, int j, int fj) {int ki, kj;int ret = 1;if (dp[i][fi][j][fj] != -1)return dp[i][fi][j][fj];int graph[55][55];memset(graph, 0, sizeof(graph));for (ki = 0; ki < nt[i].size(); ++ki) {if (nt[i][ki] == fi)continue;for (kj = 0; kj < nt[j].size(); ++kj) {if (nt[j][kj] == fj)continue;graph[ki][kj] = gao(nt[i][ki], i, nt[j][kj], j);}}ret += gao2(nt[i].size(), nt[j].size(), graph);return dp[i][fi][j][fj] = dp[j][fj][i][fi] = ret;}bool dfs(int i, int fa, int j) {if (i == j)return true;int k;for (k = 0; k < nt[i].size(); ++k) {if (nt[i][k] == fa)continue;if (dfs(nt[i][k], i, j))return true;}return false;}int DeerInZooDivOne::getmax(vector<int> A, vector<int> B) {int i, j, k, ii, jj, n;int ans = 0;n = A.size() + 1;for (k = 0; k < A.size(); ++k) {for (i = 0; i < n; ++i)nt[i].clear();for (i = 0; i < A.size(); ++i) {if (i == k)continue;nt[A[i]].push_back(B[i]);nt[B[i]].push_back(A[i]);}for (i = 0; i < n; ++i) {for (j = 0; j < n; ++j) {dp[i][n][j][n] = -1;for (ii = 0; ii < nt[i].size(); ++ii) {for (jj = 0; jj < nt[j].size(); ++jj)dp[i][nt[i][ii]][j][nt[j][jj]] = -1;}}}for (i = 0; i < n; ++i) {for (j = 0; j < n; ++j) {if (dfs(i, -1, j) == true)continue;ans = max(ans, gao(i, n, j, n));}}}return ans;}


0 0
原创粉丝点击