QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#106804#6127. Kawa ExamevirirWA 2016ms36888kbC++207.0kb2023-05-19 11:58:112023-05-19 11:58:13

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-05-19 11:58:13]
  • 评测
  • 测评结果:WA
  • 用时:2016ms
  • 内存:36888kb
  • [2023-05-19 11:58:11]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;

#define sz(x) (int)(x).size()
#define all(x) begin(x), end(x)
#define forn(i,a,b) for(int i=(a);i<(b);i++)
#define fore(i,a,b) for(int i=(a);i<=(b);i++)
#define pb push_back
#define F first
#define S second
typedef long long ll;
typedef pair<int, int> ii;
typedef vector<int> vi;
using Adj = vector<vector<int>>;

vi num, st;
vector<vector<ii>> ed;
vector<ii> edges;
vector<ii> bridges;
int Time;
template<class F>
int dfs_bicomps(int at, int par, F& f) {
	int me = num[at] = ++Time, e, y, top = me;
	for (auto pa : ed[at]) if (pa.second != par) {
		tie(y, e) = pa;
		if (num[y]) {
			top = min(top, num[y]);
			if (num[y] < me)
				st.push_back(e);
		} else {
			int si = sz(st);
			int up = dfs_bicomps(y, e, f);
			top = min(top, up);
			if (up == me) {
				st.push_back(e);
				f(vi(st.begin() + si, st.end()));
				st.resize(si);
			}
			else if (up < me) st.push_back(e);
			else { bridges.push_back(edges[e]); }
		}
	}
	return top;
}

template<class F>
void bicomps(F f) {
	num.assign(sz(ed), 0);
	forn(i,0,sz(ed)) if (!num[i]) dfs_bicomps(i, -1, f);
}

void reset()
{
	num.clear();
	st.clear();
	ed.clear();
	edges.clear();
	bridges.clear();
	Time = 0;
}

// convert bicomps into nodes, return graph
Adj MakeCompAdj(const int n, const vector<int>& a)
{
	// make bicomps
	vector<int> comp_id(n, -1);
	vector<vector<ii>> freq_comp;
	int next_comp_id = 0;
	bicomps([&](const vector<int> &edgelist) {
		unordered_set<int> node_set;
		for (const auto& eid : edgelist)
		{
			auto [u, v] = edges[eid];
			node_set.insert(u);
			node_set.insert(v);
		}
		unordered_map<int, int> cur_count;
		for (const int u : node_set)
		{
			comp_id[u] = next_comp_id;
			cur_count[a[u]]++;
		}
		freq_comp.emplace_back(all(cur_count));
		next_comp_id++;
	});

	// deal with nodes not in a bicomp
	forn(i,0,n)
	{
		if (comp_id[i] == -1)
		{
			comp_id[i] = next_comp_id++;
		}
	}

	// make bicomp graph
	Adj comp_adj(next_comp_id);
	for (const auto& [u, v] : bridges)
	{
		int u_comp = comp_id[u];
		int v_comp = comp_id[v];
		comp_adj[u_comp].pb(v_comp);
		comp_adj[v_comp].pb(u_comp);
	}
	return comp_adj;
}

void dfs(const Adj &adj, const int u, const int p, vector<bool>& vst, vector<int>& cur_tree)
{
	vst[u] = true;
	cur_tree.push_back(u);
	for (const int v : adj[u])
	{
		if (v == p) continue;
		dfs(adj, v, u, vst, cur_tree);
	}
}

// group cc's of comp_adj
vector<vector<int>> MakeTrees(const Adj& comp_adj)
{
	int comp_cnt = sz(comp_adj);
	vector<vector<int>> trees;
	vector<int> tree_max_sum;
	vector<bool> vst(comp_cnt, false);
	forn(i,0,sz(comp_adj))
	{
		if (vst[i]) continue;
		vector<int> cur_tree;
		dfs(comp_adj, i, -1, vst, cur_tree);
		trees.push_back(cur_tree);
	}
	return trees;
}

void dfs_euler(Adj &adj, const int u, const int p,
			   vector<int> &in, vector<int> &out, vector<int>& enode, vector<int>& big, int &tmr,
			   vector<int>& sz)
{
	sz[u] = 1;
	in[u] = ++tmr;
	enode[tmr] = u;
	for (const int v : adj[u])
	{
		if (v == p) continue;
		dfs_euler(adj, v, u, in, out, enode, big, tmr, sz);
		if (big[u] == -1 || sz[big[u]] < sz[v]) big[u] = v;
		sz[u] += sz[v];
	}
	forn(i, 0, sz(adj[u]))
	{
		int v = adj[u][i];
		if (sz[v] > sz[adj[u][0]]) swap(adj[u][0], adj[u][i]);
	}
	out[u] = tmr;
}

class Counter {
private:
	unordered_map<int, int> count;
	multiset<int> freq_set;

public:
	Counter(): count(), freq_set() {}

	void add(const int x)
	{
		if (count[x] != 0)
			freq_set.erase(freq_set.find(count[x]));
		count[x]++;
		freq_set.insert(count[x]);
	}

	void remove(const int x)
	{
		assert(count.find(x) != count.end());
		freq_set.erase(freq_set.find(count[x]));
		count[x]--;
		if (count[x] != 0)
			freq_set.insert(count[x]);
		else
			count.erase(x);
	}

	int most_common() const
	{
		if (freq_set.empty()) return 0;
		return *freq_set.rbegin();
	}
};

void add(const int u, const vector<int>& a, Counter& in_sub, Counter& out_sub)
{
	in_sub.add(a[u]);
	out_sub.remove(a[u]);
}

void remove(const int u, const vector<int>& a, Counter& in_sub, Counter& out_sub)
{
	in_sub.remove(a[u]);
	out_sub.add(a[u]);
}

void dfs_dsu(const Adj &adj, const vector<int>& a, const vector<int> &in, const vector<int> &out, const vector<int>& enode,
			 const vector<int>& big, const int u, const int p, const bool keep, Counter& in_sub, Counter& out_sub,
			 const int base, map<ii, int>& ans)
{
	for (const int v : adj[u])
	{
		if (v == p || v == big[u]) continue;
		dfs_dsu(adj, a, in, out, enode, big, v, u, false, in_sub, out_sub, base, ans);
	}
	if (big[u] != -1)
	{
		dfs_dsu(adj, a, in, out, enode, big, big[u], u, true, in_sub, out_sub, base, ans);
	}

	for (const int v : adj[u])
	{
		if (v == p || v == big[u]) continue;
		for (int j = in[v]; j <= out[v]; j++)
		{
			add(enode[j], a, in_sub, out_sub);
		}
	}
	add(u, a, in_sub, out_sub);
	ans[{u, p}] = base + in_sub.most_common() + out_sub.most_common();

	if (!keep)
	{
		for (int j = in[u]; j <= out[u]; j++) remove(enode[j], a, in_sub, out_sub);
	}
}

void GetTreeAns(Adj& adj, const vector<int>& a, const vector<int>& nodes, const int base, map<ii, int>& ans,
				vector<int>& in, vector<int>& out, vector<int>& enode, vector<int>& big, vector<int>& sz)
{
	int rt = nodes[0];

	// shared total
	Counter in_sub, out_sub;
	for (const int u : nodes) out_sub.add(a[u]);

	// euler tour
	int tmr = -1;
	dfs_euler(adj, rt, -1, in, out, enode, big, tmr, sz);

	dfs_dsu(adj, a, in, out, enode, big, rt, -1, false, in_sub, out_sub, base, ans);
}

void solve()
{
	reset();

	int n, m;
	cin >> n >> m;
	vector<int> a(n);
	forn(i,0,n)
	{
		cin>>a[i];
		a[i]--;
	}

	// read ori graph
	ed.resize(n);
	forn(i,0,m)
	{
		int u,v; cin>>u>>v; u--; v--;
		ed[u].emplace_back(v, i);
		ed[v].emplace_back(u, i);
		edges.pb({u, v});
	}

	// make bicomp graph
	Adj comp_adj = MakeCompAdj(n, a);

	// make tree groups
	vector<vector<int>> trees = MakeTrees(comp_adj);
	int tree_cnt = sz(trees);

	vector<int> tree_max(tree_cnt);
	forn(i, 0, tree_cnt)
	{
		unordered_map<int, int> cur_cnt;
		for (const int u : trees[i]) cur_cnt[a[u]]++;
		for (const auto& [color, count] : cur_cnt)
		{
			tree_max[i] = max(tree_max[i], count);
		}
	}

	// process each tree
	int max_pre = 0;
	int max_suf = accumulate(tree_max.begin() + 1, tree_max.end(), 0);
	map<ii, int> ans;
	vector<int> in(n), out(n), enode(n), big(n, -1);
	vector<int> sz;
	sz.resize(n);
	forn(i, 0, tree_cnt)
	{
		int base = max_pre + max_suf;
		GetTreeAns(comp_adj, a, trees[i], base, ans, in, out, enode, big, sz);

		max_pre += tree_max[i];
		if (i + 1 < tree_cnt) max_suf -= tree_max[i + 1];
	}

	forn(i,0,sz(edges))
	{
		if (i > 0) cout << ' ';
		ii e = edges[i];
		if (ans.find(e) == ans.end()) swap(e.first, e.second);
		if (ans.find(e) == ans.end()) cout << max_pre;
		else cout << ans[e];
	}
	cout<<'\n';
}

int main()
{
	cin.tie(0)->sync_with_stdio(0);

	int t; cin>>t;
	fore(i,1,t) solve();

	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 2ms
memory: 3496kb

input:

3
7 5
1 2 1 2 1 2 1
1 2
1 3
2 4
5 6
5 7
3 3
1 2 3
1 2
1 3
2 3
2 3
12345 54321
1 2
1 2
1 1

output:

6 5 5 5 4
1 1 1
1 1 1

result:

ok 3 lines

Test #2:

score: -100
Wrong Answer
time: 2016ms
memory: 36888kb

input:

5557
2 7
79960 79960
2 2
1 1
1 1
2 2
1 1
2 1
1 2
9 8
21881 70740 70740 21881 22458 22458 639 21881 70740
3 3
1 6
5 8
7 5
5 7
2 3
5 1
7 6
6 7
13064 20716 6746 13064 6746 69225
5 5
4 1
4 1
1 6
4 5
3 2
3 2
8 4
45146 14400 45146 45146 14400 72969 14400 45146
8 6
1 3
4 6
8 3
18 13
48132 37949 92338 92338...

output:

1 1 1 1 1 1 1
5 5 5 5 5 5 6 5
3 3 3 3 3 3 3
7 7 7 7
9 9 9 9 9 9 9 9 9 10 9 9 9
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
7 8
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
9 9 9
16 16 16 16 16 17 16 16
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
1 1 1 1 1 1 1 1 1...

result:

wrong answer 1st lines differ - expected: '2 2 2 2 2 2 2', found: '1 1 1 1 1 1 1'