This repository has been archived on 2022-06-22. You can view files and clone it, but cannot push or open issues or pull requests.
usaco-guide/content/1_Intro/Factors_Choosing.mdx
2020-07-14 21:02:57 -04:00

229 lines
6.6 KiB
Text

---
id: factors-choosing
title: "Factors to Consider When Choosing a Language"
author: Benjamin Qi
description: Reasons why choice of language matters significantly outside of USACO Bronze.
---
## Notes
- USACO problemsetters don't always test Java (and rarely Python) solutions when setting constraints.
- Python lacks a data structure that keeps its keys in sorted order (the equivalent of `set` in C++), which is required for some silver problems.
- Java lacks features such as `#define`, `typedef`, and `auto` that are present in C++ (which some contestants rely on extensively, see "Shortening C++").
## Time Limit
Although both Python and Java receive two times the C++ time limit in USACO, this is not the case for most other websites (ex. CodeForces). Even with the extended time limits, Python and Java sometimes have trouble passing.
(may need to rewrite these solutions so they are more similar)
- Rewriting the C++ solution for [USACO Silver Wormsort](http://www.usaco.org/index.php?page=viewproblem2&cpid=992) in Python receives TLE (Time Limit Exceeded) on 2/10 cases. I'm not sure whether it is possible to pass this problem with Python.
<spoiler title="Python3 8/10 Solution">
```py
# 8/10 test cases ...
fin = open("wormsort.in","r")
lines = [line for line in fin]
N,M = map(int,lines[0].split())
p = list(map(lambda x: int(x)-1,lines[1].split()))
ed = []
for i in range(2,len(lines)):
a,b,w = map(int,lines[i].split())
a -= 1
b -= 1
ed.append([w,a,b])
ed.sort()
ed.reverse()
adj = [[] for i in range(N)]
vis = [0 for i in range(N)]
cnt = 0
def dfs(x):
global cnt
if vis[x] != 0:
return
vis[x] = cnt
for i in adj[x]:
dfs(i)
def ok(mid):
global cnt
for i in range(N):
vis[i] = 0
adj[i].clear()
for i in range(mid):
a,b = ed[i][1],ed[i][2]
adj[a].append(b)
adj[b].append(a)
for i in range(N):
if vis[i] == 0:
cnt += 1
todo = [i]
ind = 0
while ind < len(todo):
x = todo[ind]
ind += 1
vis[x] = cnt
for i in adj[x]:
if vis[i] == 0:
vis[i] = -cnt
todo.append(i)
ok = True
for i in range(N):
if vis[i] != vis[p[i]]:
ok = False
return ok
lo,hi = 0,M
while lo < hi:
mid = (lo+hi)//2
if ok(mid):
hi = mid
else:
lo = mid+1
fout = open("wormsort.out","w")
fout.write(str(-1 if lo == 0 else ed[lo-1][0]))
fout.write('\n')
```
</spoiler>
- A similar solution in Java requires almost 3s, which is fairly close to the time limit of 4s.
<spoiler title="Java Solution">
```java
import java.io.*; // from Nick Wu
import java.util.*;
public class wormsort {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new FileReader("wormsort.in"));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
loc = new int[n];
component = new int[n];
edges = new LinkedList[n];
for(int i = 0; i < n; i++) edges[i] = new LinkedList<>();
lhs = new int[m];
rhs = new int[m];
weight = new int[m];
st = new StringTokenizer(br.readLine());
for(int i = 0; i < n; i++) loc[i] = Integer.parseInt(st.nextToken())-1;
for(int i = 0; i < m; i++) {
st = new StringTokenizer(br.readLine());
lhs[i] = Integer.parseInt(st.nextToken())-1;
rhs[i] = Integer.parseInt(st.nextToken())-1;
weight[i] = Integer.parseInt(st.nextToken());
}
br.close();
int minW = 0;
int maxW = 1000000001;
while(minW != maxW) {
int mid = (minW + maxW + 1) / 2;
if(valid(mid)) minW = mid;
else maxW = mid-1;
}
if(minW > 1e9) minW = -1;
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("wormsort.out")));
pw.println(minW);
pw.close();
}
static int[] loc, lhs, rhs, weight;
static LinkedList<Integer>[] edges;
static int[] component;
private static void dfs(int curr, int label) {
if(component[curr] == label) return;
component[curr] = label;
for(int child: edges[curr]) dfs(child, label);
}
private static boolean valid(int minW) {
Arrays.fill(component, -1);
for(int i = 0; i < edges.length; i++) edges[i].clear();
for(int i = 0; i < lhs.length; i++) {
if(weight[i] >= minW) {
edges[lhs[i]].add(rhs[i]);
edges[rhs[i]].add(lhs[i]);
}
}
int numcomps = 0;
for(int i = 0; i < component.length; i++) {
if(component[i] < 0) {
dfs(i, numcomps++);
}
}
for(int i = 0; i < loc.length; i++) {
if(component[i] != component[loc[i]]) return false;
}
return true;
}
}
```
</spoiler>
- A comparable C++ solution runs in less than 700ms.
<spoiler title="C++ Solution">
```cpp
#include <bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
const int MX = 1e5+5;
int loc[MX], comp[MX], lhs[MX], rhs[MX], wei[MX];
vi adj[MX];
int n,m;
void dfs(int cur, int label) {
if (comp[cur] == label) return;
comp[cur] = label;
for (int c: adj[cur]) dfs(c,label);
}
bool valid(int minW) {
for (int i = 0; i < n; ++i) {
comp[i] = -1;
adj[i].clear();
}
for (int i = 0; i < m; ++i) if (wei[i] >= minW)
adj[lhs[i]].push_back(rhs[i]), adj[rhs[i]].push_back(lhs[i]);
int numComps = 0;
for (int i = 0; i < n; ++i) if (comp[i] < 0)
dfs(i,numComps++);
for (int i = 0; i < n; ++i)
if (comp[i] != comp[loc[i]]) return 0;
return 1;
}
int main() {
ios_base::sync_with_stdio(0); cin.tie(0);
freopen("wormsort.in","r",stdin);
freopen("wormsort.out","w",stdout);
cin >> n >> m;
for (int i = 0; i < n; ++i) cin >> loc[i], loc[i] --;
for (int i = 0; i < m; ++i) {
cin >> lhs[i], lhs[i] --;
cin >> rhs[i], rhs[i] --;
cin >> wei[i];
}
int minW = 0, maxW = (int)1e9+1;
while (minW != maxW) {
int mid = (minW+maxW+1)/2;
if (valid(mid)) minW = mid;
else maxW = mid-1;
}
if (minW > 1e9) minW = -1;
cout << minW;
}
```
</spoiler>