Skip to content

Commit 2d68618

Browse files
committed
Adding submissions
1 parent 50ae90d commit 2d68618

File tree

1 file changed

+144
-0
lines changed
  • kattis/The 2014 Nordic Collegiate Programming Contest

1 file changed

+144
-0
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// https://ncpc14.kattis.com/problems/outing
2+
3+
#include<bits/stdc++.h>
4+
using namespace std;
5+
#define __ ios_base::sync_with_stdio(0); cin.tie(0);
6+
#define endl '\n'
7+
#define foreach(it, x) for (__typeof (x).begin() it = (x).begin(); it != (x).end(); ++it)
8+
#define all(x) x.begin(),x.end()
9+
#define D(x) cout << #x " = " << (x) << endl;
10+
11+
template <class T> string toStr(const T &x)
12+
{ stringstream s; s << x; return s.str(); }
13+
14+
template <class T> int toInt(const T &x)
15+
{ stringstream s; s << x; int r; s >> r; return r; }
16+
17+
int dx[8] = {-1,-1,-1,0,1,1, 1, 0};
18+
int dy[8] = {-1, 0, 1,1,1,0,-1,-1};
19+
20+
int dp[1111][1111][11];
21+
22+
void dfs (int i, vector< vector<int> > &G, vector<int> &visited, int &size) {
23+
if (!visited[i]) {
24+
size ++;
25+
visited[i] = true;
26+
for (int j = 0; j < G[i].size(); ++j) {
27+
int next = G[i][j];
28+
dfs (next, G, visited, size);
29+
}
30+
}
31+
}
32+
33+
int go (int i, int k, bool taken, int sum, vector<int> &toTake) {
34+
if (dp[i][sum][taken] != -1) return dp[i][sum][taken];
35+
if (i >= toTake.size()) return sum;
36+
37+
int a = 0, b = 0;
38+
if (sum + toTake[i] <= k)
39+
a = go (i + 1, k, true, sum + toTake[i], toTake);
40+
b = go (i + 1, k, taken, sum, toTake);
41+
42+
return dp[i][sum][taken] = max(a, b);
43+
}
44+
45+
/** Krustal implementation
46+
* Complexity: O(E log V)
47+
**/
48+
49+
const int mx = 1111;
50+
51+
struct edge {
52+
int start, end, weight;
53+
edge(){} edge(int start, int end, int weight) : start(start), end(end), weight(weight) {}
54+
bool operator < (const edge &that) const {
55+
// Change < by > to find maximum spanning tree
56+
return weight > that.weight;
57+
}
58+
};
59+
60+
/** Begin union find
61+
* Complexity: O(m log n) where m is the number of the operation
62+
* and n are the number of objects, in practice is almost O(m)
63+
**/
64+
int p[mx];
65+
66+
void init_set (int &n) {
67+
for (int i = 0; i <= n; ++i) p[i] = i;
68+
}
69+
70+
int find_set (int x) {
71+
return p[x] == x ? p[x] : p[x] = find_set(p[x]);
72+
}
73+
74+
void join (int x, int y) {
75+
p[find_set(x)] = find_set(y);
76+
}
77+
/** End union find **/
78+
79+
/** e is a vector with all edges of the graph
80+
* return graph of MST
81+
**/
82+
int krustal (vector<edge> &e, int &n, int &k, vector< vector<int> > &G, vector< vector<int> > &G2) {
83+
vector<int> visited (n + 1, 0);
84+
vector<int> visited2 (n + 1, 0);
85+
vector< int > toTake;
86+
int rest = 0;
87+
88+
sort(e.begin(), e.end());
89+
init_set(n);
90+
91+
for (int i = 0 ; i < e.size(); ++i) {
92+
int u = e[i].start;
93+
int v = e[i].end;
94+
int w = e[i].weight;
95+
96+
if (find_set(u) == find_set(v)) {
97+
if (!visited[u]) {
98+
int sizeCycle = 0;
99+
int totalNodes = 0;
100+
dfs (u, G, visited, sizeCycle);
101+
dfs (u, G2, visited2, totalNodes);
102+
103+
if (sizeCycle <= k) {
104+
toTake.push_back(sizeCycle);
105+
rest += totalNodes - sizeCycle;
106+
}
107+
}
108+
}
109+
110+
join(u, v);
111+
}
112+
113+
memset(dp, -1, sizeof dp);
114+
int ans = go (0, k, 0, 0, toTake);
115+
int free = k - ans;
116+
if (rest >= free) ans = k;
117+
else ans += rest;
118+
return ans;
119+
}
120+
121+
int main () {
122+
int n, k, b;
123+
while (cin >> n >> k) {
124+
125+
vector<edge> v(n);
126+
vector< vector<int> > G(n + 1), G2(n + 1);
127+
edge e;
128+
129+
for (int i = 0; i < n; ++i) {
130+
cin >> b;
131+
132+
e.start = i + 1;
133+
e.end = b;
134+
e.weight = 1;
135+
v[i] = e;
136+
137+
G[i + 1].push_back(b);
138+
G2[b].push_back(i + 1);
139+
}
140+
141+
int ans = krustal(v, n, k, G, G2);
142+
cout << ans << endl;
143+
}
144+
}

0 commit comments

Comments
 (0)