NC245360. Cactusophobia
描述
输入描述
第一行输入两个整数 n, m 分别代表顶点数和边数。
下面 m 行包含三个整数 u, v, c 表示一条从 u 连向 v 颜色为 c 的边。输入数据保证是一个仙人掌图。
输出描述
输出最多颜色数。
示例1
输入:
4 4 1 2 4 2 3 1 3 4 2 4 2 3
输出:
3
示例2
输入:
7 9 1 2 1 2 3 4 3 1 5 1 4 5 4 5 2 5 1 6 1 6 4 6 7 6 7 1 3
输出:
6
C++(clang++ 11.0.1) 解法, 执行用时: 18ms, 内存消耗: 4868K, 提交时间: 2022-11-28 11:07:27
#include <bits/stdc++.h> #define fi first #define se second using namespace std; typedef pair<int, int> P ; const int maxn = 4e4 + 10, INF = 0x3f3f3f3f ; struct edge { int to, cap, rev ; edge () {} edge (int _to, int _cap, int _rev) {to = _to, cap = _cap, rev = _rev;} } ; vector<edge> G[maxn] ; int level[maxn], iter[maxn] ; void addEdge (int from, int to, int cap) { //printf("%d %d %d\n", from, to, cap) ; G[from].push_back (edge (to, cap, G[to].size())) ; G[to].push_back (edge (from, 0, G[from].size() - 1)) ; } void bfs (int s) { memset (level, -1, sizeof level) ; queue<int> que ; que.push (s); level[s] = 0 ; while (!que.empty()) { int v = que.front(); que.pop() ; for (int i = 0; i < G[v].size(); i ++) { edge e = G[v][i] ; if (e.cap > 0 && level[e.to] < 0) { level[e.to] = level[v] + 1 ; que.push (e.to) ; } } } } int dfs (int v, int t, int f) { if (v == t) return f ; for (int &i = iter[v]; i < G[v].size(); i ++) { edge &e = G[v][i] ; if (e.cap > 0 && level[e.to] > level[v]) { int d = dfs (e.to, t, min (f, e.cap)) ; if (d > 0) { e.cap -= d ; G[e.to][e.rev].cap += d ; return d ; } } } return 0 ; } int maxflow (int s, int t) { int flow = 0 ; for (;;) { bfs (s) ; if (level[t] < 0) return flow ; memset (iter, 0, sizeof iter) ; int f ; while ((f = dfs (s, t, INF)) > 0) flow += f ; } } int n, m ; vector<P> g[maxn] ; int dfn[maxn], low[maxn], stk[maxn], num, top, cnt ; vector<int> dcc[maxn] ; int color[maxn] ; void add_Edge (int u, int v, int id) { g[u].push_back (P (v, id)) ; g[v].push_back (P (u, id)) ; } void tarjan (int v, int fa) { dfn[v] = low[v] = ++ num ; for (int i = 0; i < g[v].size(); i ++) { int y = g[v][i].fi, id = g[v][i].se ; if (y == fa) continue ; if (!dfn[y]) { stk[++ top] = id ; tarjan (y, v) ; low[v] = min (low[v], low[y]) ; if (low[y] >= dfn[v]) { cnt ++ ; while (stk[top] != id) dcc[cnt].push_back (stk[top --]) ; dcc[cnt].push_back (stk[top --]) ; } } else if (dfn[y] < dfn[v]) { stk[++ top] = id ; low[v] = min (low[v], dfn[y]) ; } } } int main() { cin >> n >> m ; for (int i = 1; i <= m; i ++) { int u, v, c ; scanf("%d%d%d", &u, &v, &c) ; color[i] = c ; add_Edge (u, v, i) ; } tarjan (1, 0) ; int s = 0, t = cnt + m + 1 ; for (int i = 1; i <= cnt; i ++) { if (dcc[i].size() == 1) addEdge (s, i, 1) ; else addEdge (s, i, dcc[i].size() - 1) ; for (int j = 0; j < dcc[i].size(); j ++) addEdge (i, cnt + color[dcc[i][j]], 1) ; } for (int i = 1; i <= m; i ++) addEdge (cnt + i, t, 1) ; printf("%d\n", maxflow (s, t)) ; return 0 ; }