Problem Link: USACO
I understand the official algorithm, but my previous algorithm timed out despite being similar to the official solution.
My previous algorithm timed out for the last 5 test cases. Here’s a description: Get all the connected components using dfs. Then for each of the connected components, use binary search to get the closest distance from that component to the component with farm 1 and from the component containing farm n.
I don’t understand why this times out even though I am presumably checking n nodes.
Your algorithm seems correct. Could you paste your code? Would make it easier to debug(How to ask for help on a problem)
Are you sure about that? A common mistake on the binary search is which array you’re binary searching on… Check my code here for more information on how to do this.
I am in the process of commenting my code. I will share it with you alll soon.
Edit:
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <math.h>
#include <set>
#include <map>
#include <string>
using namespace std;
typedef long long ll;
const ll maxn = 1e5 + 10;
const ll zer = 0;
const ll bignumber = 9999999999999;
//input
ll n, m;
//adjacency list
vector <ll> adj[maxn];
//visited array for dfs
bool visited[maxn];
bool works(ll constraint) {
return true;
}
//clear adjacency list and visited
void init() {
for (ll i = 1; i <= n; i++) {
adj[i].clear();
visited[i] = false;
}
}
//stores the connected components
vector <vector <ll>> cc;
//stores the ids of each of the nodes
ll id[maxn];
//used to get the connected components
vector <ll> temp;
//self-explanatory dfs
void dfs(ll node) {
for (ll k = 0; k < adj[node].size(); k++) {
if (!visited[adj[node][k]]) {
visited[adj[node][k]] = true;
temp.push_back(adj[node][k]);
dfs(adj[node][k]);
}
}
}
//computes the ID of each of the n nodes
void computeID() {
for (ll k = 0; k < cc.size(); k++) {
for (ll i = 0; i < cc[k].size(); i++) {
id[cc[k][i]] = k;
}
}
}
void floodfill() {
//clear everything from previous test cases
cc.clear();
temp.clear();
for (ll i = 1; i <= n; i++) id[i] = -1;
//get the connected components and build cc
for (ll i = 1; i <= n; i++) {
if (!visited[i]) {
visited[i] = true;
temp.push_back(i);
dfs(i);
sort(temp.begin(), temp.end());
cc.push_back(temp);
temp.clear();
}
}
//compute the IDs of each of the n nodes
computeID();
}
//since lower bound returns the first index >=, I might need the returned index or the returned index minus 1 (if possible)
//a and b are the ids of two connected components
ll calculateCost(ll a, ll b) {
//If they are the same component, return 0
if (a == b) {
return 0;
}
//set ret to a big number
ll ret = bignumber;
//traverse the array with smaller size
if (cc[a] > cc[b]) {
swap(a, b);
}
//check each element of cc[a] and binary search on cc[b]
for (ll k = 0; k < cc[a].size(); k++) {
ll index1 = lower_bound(cc[b].begin(), cc[b].end(), cc[a][k]) - cc[b].begin();
ll index2 = index1 - 1;
if (index1 >= 0 && index1 < cc[b].size()) {
ret = min(ret, (cc[b][index1] - cc[a][k]) * (cc[b][index1] - cc[a][k]));
}
if (index2 >= 0 && index2 < cc[b].size()) {
ret = min(ret, (cc[b][index2] - cc[a][k]) * (cc[b][index2] - cc[a][k]));
}
}
return ret;
}
void solve()
{
cin >> n >> m;
init();
for (ll i = 0; i < m; i++) {
ll a, b;
cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
//get the cc's
floodfill();
//If 1 and N are in the same component, print 1
if (id[1] == id[n]) {
cout << 0 << endl;
return;
}
//This covers the case where only one path is built
ll ans = calculateCost(id[1], id[n]);
//pick all middle components and get the cost
for (ll middle = 0; middle < cc.size(); middle++) {
ll cost1 = calculateCost(id[1], middle);
ll cost2 = calculateCost(middle, id[n]);
ll totalcost = cost1 + cost2;
ans = min(ans, totalcost);
}
cout << ans << endl;
}
int main()
{
//init();
//do all test cases
ll t;
cin >> t;
while (t--) {
solve();
}
}
1 Like
Have you tried stress testing it?
I tried using the code in the usaco guide solution but it only passed the first 5 test cases.
Please see the updated code on the same link provided.
It worked. All I had to do was to make sure that I was binary searching on the larger component
1 Like