Competitive programming problem I am stuck in - c++

So there is a list of points (x1,y1,z1),(x2,y2,z2),...(xn,yn,zn).
You can perform an operation O on any number of these points.
Operation O results in (x,y,z)= (max(x1,x2,...xn),max(y1,y2,...yn),max(z1,z2,...zn)).
Given (x,y,z), you need to determine whether it is possible to perform operation O on some of the points in the list to get (x,y,z) as a result.
For eg: You are given points(1,2,1),(3,1,4),(5,2,1).
Can you perform O operation to get 1) (3,2,1) 2) (1,1,1)
First line contains n and q i.e the number of points and no. of queries
Next n lines contain the n points space seperated
Next q lines contain the q points which are the queries
1<=q<=10^5
1<=n<=10^5
x,y,z are integers
Input:
2 2
1 3 5
5 3 1
5 3 5
3 3 3
Expected Output:
YES
NO
My logic:
for (int i = 0; i < q; i++)
{
cin>>x>>y>>z;
for (int j = 0; j < n; j++)
{
if(arr[j][0]==x && arr[j][1]<=y && arr[j][2]<=z)
first=1;
if(arr[j][0]<=x && arr[j][1]==y && arr[j][2]<=z)
second=1;
if(arr[j][0]<=x && arr[j][1]<=y && arr[j][2]==z)
third=1;
if(first+second+third==3)
break;
}
if(first+second+third==3)
cout<<"YES\n";
else
{
cout<<"NO\n";
}
first=0;
second=0;
third=0;
}
Note: Here arr[][] contains the given coordinates.
for every x y z in queries q I am performing this operation.
Few test cases are failing giving me a runtime error (Time limit Exceeded). Is there a better way to do this.

Your solution is correct but slow, has O(q * n) complexity which is 10^10 at maximum, too much.
I've solved your task using sorting plus merging search, which has O(n log n + q log q) complexity.
The algorithm is as follows:
For each of three cases, (x, y, z), (y, x, z), (z, x, y), signified as coordinates (i0, i1, i2), we do next:
Sort all points and queries by tuple (i0, i1, i2).
Among each equal coordinates i0 compute cumulative minimum of i2.
Merge sorted points and queries next way: For each range of queries and points with equal i0 and i1 take rightmost minimal i2. If such minimal i2 for point is greater than query's i2 then answer for this query is NO, otherwise is probably YES (probably meaning that it should be YES for all 3 orderings of (x, y, z)/(y, x, z)/(z, x, y)).
Basically algorithm above does same thing as your algorithm does, it finds point with equal x, y, or z so that other two coordinates are not greater. But does it through fast algorithm of merging two sorted arrays. So that merging itself takes just O(q + n) time, while whole algorithm time is dominated by sorting algorithms taking O(q log q + n log n) time.
Try it online!
#include <iostream>
#include <vector>
#include <algorithm>
#include <tuple>
using namespace std;
typedef int CoordT;
typedef tuple<CoordT, CoordT, CoordT> CoordsT;
typedef vector<CoordsT> CoordsVecT;
template <size_t i0, size_t i1, size_t i2>
static void Solve(CoordsVecT const & ps, CoordsVecT const & qs, vector<bool> & yes) {
auto Prep = [&](auto & s, auto const & o){
s.clear();
s.reserve(o.size());
for (size_t i = 0; i < o.size(); ++i)
s.push_back(make_tuple(get<0>(o[i]), get<1>(o[i]), get<2>(o[i]), i));
sort(s.begin(), s.end(), [](auto const & l, auto const & r) -> bool {
return get<i0>(l) < get<i0>(r) || get<i0>(l) == get<i0>(r) && (
get<i1>(l) < get<i1>(r) || get<i1>(l) == get<i1>(r) &&
get<i2>(l) < get<i2>(r)
);
});
};
vector< tuple<CoordT, CoordT, CoordT, size_t> > sps, sqs;
Prep(sps, ps);
Prep(sqs, qs);
vector<CoordT> mins2(sps.size());
CoordT cmin2 = 0;
for (size_t i = 0; i < sps.size(); ++i) {
if (i == 0 || get<i0>(sps[i - 1]) != get<i0>(sps[i]))
cmin2 = get<i2>(sps[i]);
cmin2 = std::min(cmin2, get<i2>(sps[i]));
mins2[i] = cmin2;
}
for (size_t iq = 0, ip = 0; iq < sqs.size(); ++iq) {
auto & cyes = yes[get<3>(sqs[iq])];
if (!cyes)
continue;
while (ip < sps.size() && get<0>(sps[ip]) < get<0>(sqs[iq]))
++ip;
if (ip >= sps.size() || get<0>(sps[ip]) != get<0>(sqs[iq])) {
cyes = false;
continue;
}
while (ip + 1 < sps.size() && get<0>(sps[ip + 1]) == get<0>(sqs[iq]) && get<1>(sps[ip + 1]) <= get<1>(sqs[iq]))
++ip;
if (ip >= sps.size() || get<1>(sps[ip]) > get<1>(sqs[iq]) || mins2[ip] > get<2>(sqs[iq])) {
cyes = false;
continue;
}
}
}
int main() {
size_t n = 0, q = 0;
cin >> n >> q;
auto Input = [](CoordsVecT & v, size_t cnt) {
v.reserve(v.size() + cnt);
for (size_t i = 0; i < cnt; ++i) {
CoordT x, y, z;
cin >> x >> y >> z;
v.push_back(make_tuple(x, y, z));
}
};
CoordsVecT ps, qs;
Input(ps, n);
Input(qs, q);
vector<bool> yes(qs.size(), true);
Solve<0, 1, 2>(ps, qs, yes);
Solve<1, 0, 2>(ps, qs, yes);
Solve<2, 0, 1>(ps, qs, yes);
for (size_t i = 0; i < qs.size(); ++i)
cout << (yes[i] ? "YES" : "NO") << endl;
return 0;
}
Input:
2 2
1 3 5
5 3 1
5 3 5
3 3 3
Output:
YES
NO

Related

Equality test function

Below is a function which aims to perform an equality test between adjacent numbers in a one dimensional vector.
This 1D vector will have values which will represent an nxn grid. [ v is the vector]
When they are equal it returns false.
For example consider this 3x3 grid:
i\j| 0 | 1 | 2
0 | 1 | 2 | 3
1 | 4 | 5 | 6
2 | 7 | 8 | 9
The issue with the code I wrote is that not all of the numbers in the grid will have 4 other adjacent numbers and testing for indexes which don't exist e.g when trying to compare the number above the top left number in the grid (1 in the example) might lead to some inaccurate outcomes.
In addition to this what I wrote seems not to be the most efficient way to go about it. Surely there could be a simpler way to do this than having to list 5 new variables?
for( int i= 0; i < n ; i++ ){
for( int j = 0; j < n; j++){
int x = v[convert(i, j, n)];
int c = v[convert(i-1, j, n)];
int s = v[convert(i+1, j, n)];
int b = v[convert(i, j+1, n)];
int n = v[convert(i, j-1, n)];
if (x == c || x == s || x == b || x == n ) {
return false;
}
}
}
//another function used to convert 2d into 1D index
int convert(int row, int col, int rowlen){
return row*rowlen+col;
}
I would appreciate any help.
If you want an efficient way to do this, you should consider the cache locality of your values, how much index conversion you do, how many bounds tests you do, and how many comparisons are needed.
First thing to note is that you do not need to compare to the left and above when you're already comparing to the right and below. This is because the left/up test will happen when testing to the right/down on the next iteration. So immediately, that halves the amount of testing.
A first optimization would be to split the operation into row tests and column tests:
// Test adjacency in rows
for (const int *rowptr = v, *end = v + n * n;
rowptr != end;
rowptr += n)
{
for (int col = 1; col < n; col++) {
if (rowptr[col-1] == rowptr[col]) return false;
}
}
// Test adjacency in columns
for (const int *row0ptr = v, *row1ptr = v + n, *end = v + n * n;
row1ptr != end;
row0ptr = row1ptr, row1ptr += n)
{
for (int col = 0; col < n; col++) {
if (row0ptr[col] == row1ptr[col]) return false;
}
}
To avoid making two passes through the entire array, you'd need to combine these, but it starts getting a bit messy. Notice how the two separate passes currently have different bounds (the row-tests loop from column 1 to n, whereas the column tests loop from row 0 to n-1).
Combining the loops would only make sense if n is quite large and if it's absolutely critical that this piece of code is fast. The idea is to perform a single pass through the entire array, avoiding any issues with stuff like L1 cache misses on the second pass.
It would look something like this:
const int *row0ptr = v, *row1ptr = v + n, *end = v + n * n
for ( ; row1ptr != end; row0ptr = row1ptr, row1ptr += n)
{
// Test first column
if (row0ptr[0] == row1ptr[0]) return false;
// Test row0 and remaining columns
for (int col = 1; col < n; col++) {
if (row0ptr[col-1] == row0ptr[col]) return false;
if (row0ptr[col] == row1ptr[col]) return false;
}
}
// Test last row
for (int col = 1; col < n; col++) {
if (row0ptr[col-1] == row0ptr[col]) return false;
}
First I'd recommend breaking up the logic because it's getting quite convoluted. But something like this works, it avoids going outside the grid by adding extra checks on i and j and it may avoid unnecessary calls to convert since if one of the earlier tests is true the later tests aren't performed.
int x = v[convert(i, j, n)];
if (i > 0 && x == v[convert(i-1, j, n)])
return false;
if (i < n - 1 && x == v[convert(i+1, j, n)])
return false;
if (j > 0 && x == v[convert(i, j-1, n)])
return false;
if (j < n - 1 && x == v[convert(i, j+1, n)])
return false;

Find the number of pairs of positive integers satisfying the inequality

I'm trying to solve a programming problem where I have to display the number of positive integer solutions of the inequality x² + y² < n, where n is given by the user. I've already written a code that seems to work but not as fast as I'd like it to. Is there any way to speed it up?
My current code:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
long long n, i, r, k, p, a;
cin >> k;
while (k--)
{
r = 0;
cin >> n;
p = sqrt(n);
for (i = 1; i <= p; i++)
{
a = sqrt(n - (i * i));
r += a;
if ((((i * i) + (a * a)) == n) && (a > 0))
{
r--;
}
}
cout << r << "\n";
}
return 0;
}
Edit:
This is a solution for this task.
The task in English:
Find the number of natural solutions (x≥1, y≥1) of the inequality x²+y² < n, where 0 < n < 2147483647. For example, for n=10 there are 4 solutions: (1,1), (1,2), (2,1), (2,2).
Input
In the first line of input the number of test cases k is given. In the next k lines, there are the n values given.
Output
In the output, you have to display in separate lines the number of natural solutions of the inequality.
Example
Input:
2
10
11
Output:
4
6
Your solution seems fast already. The main possibility to reduce the time spent is to suppress the call to sqrtin the loop. This is obtained by considering that the value a = sqrt(n - (i * i)) does not vary very much from one iteration to the next one.
Here is the code:
r = 0;
p = sqrt(n);
if ((p*p) == n) p--;
a = p;
for (long long i = 1; i <= p; i++)
{
while ((n-i*i) <= a*a) {
--a;
}
r += a;
}

How should I implement a flood fill function to my c++ program?

Im currently looking to turn something like this:
.............
.............
..XXX.....X..
..XXX.....X..
..XXX........
..XXX........
..XXXXXXX....
..XXXXXXX....
..XXXXXXX....
.............
.............
into this:
.............
.............
..XXX.....O..
..XXX.....O..
..XXX........
..XXX........
..XXXXXXX....
..XXXXXXX....
..XXXXXXX....
.............
.............
with the user entering ./a.exe input4.txt floodfill 2 10 o
I believe im going to need to implement some recursion into the program to be able to only look at indexes that match that of the user pointer (including positions of up, down, left, and right) instead of reading the entire vector (which i wouldn't mind doing but dont see how i would begin doing so).
here is the code I have so far for the flood fill function:
void floodfilll(vector<vector<char>> &vec, int x, int y, char r, char dum)
{
int ii;
ii = 0;
int jj;
jj = 0;
for (int i = 0; i < vec.size(); i ++) {
for (int j = 0; j < vec[i].size(); j++) {
if (vec[i][j] == r) {
vec[i][j] == r;
if ((i + ii) > 0) {
if (vec[i-1][j] == r)
vec[i-1][j] = dum;
vec[i][j] == r;
ii--;
floodfilll(vec, x + ii, y, r, dum);
}
if ((j + jj) > 0) {
if(vec[i][j-1] != r)
vec[i][j-1] = dum;
vec[i][j] == r;
jj--;
floodfilll(vec, x, y + jj, r, dum);
}
if ((i + ii)<vec.size()) {
if (vec[i+1][j] != r)
vec[i+1][j] = dum;
vec[i][j] == r;
ii++;
floodfilll(vec, x + ii, y, r, dum);
}
if ((j + jj)<vec[i].size()) {
if (vec[i][j+1] != r)
vec[i][j+1] = dum;
vec[i][j] == r;
jj++;
floodfilll(vec, x, y + jj, r, dum);
}
}
}
replacee(vec, dum, r);
}
}
NOTE: Im using a function called replacee to replace Var dum, with Var R. Var dum is assigned 'i' and r is 'X'.
Also, the text file is parsed as a 2d vector of char's (char)**
Its just the way the rest of my program is based. Here is the replace function:
void replacee(vector<vector<char>> &vec, char oldd, char neww)
{
for (vector<char> &v : vec) // reference to innver vector
{
replace(v.begin(), v.end(), oldd, neww); // standard library algorithm
}
}
This is the int main file im using:
int main(int argc, char* argv[]) {
fstream fin; char ch;
string name (argv[1]); //File Name.
vector<vector<char>> data;
// 2D Vector.
vector<char> temp;
// Temporary vector to be pushed
// into vec, since its a vector of vectors.
fin.open(name.c_str(),ios::in);
// Assume name as an arbitary file.
string argument2 (argv[2]);
while(fin)
{
ch = fin.get();
if(ch!='\n') {
temp.push_back(ch);
}
else
{
data.push_back(temp);
temp.clear();
}
}
if (argument2 == "floodfill") {
string argument3 (argv[3]);
string argument4 (argv[4]);
string argument5 (argv[5]);
int x = 0;
int y = 0;
stringstream xx(argument3);
stringstream yy(argument4);
xx >> x;
yy >> y;
floodfilll(data, x, y, argument5[0], 'i');
for (int m = 0; m < data.size(); m ++) {
for (int n = 0; n < data[m].size(); n++) {
cout << data[m][n];
}
cout << endl;
}
}
fin.close();
}
Sorry if it looks like im just pasting code for grabs, this is incase anyone has a solution outside my mode of thought. The int main and replacee functions work as intended. I just need help coming up with a way to make floodfilll work correctly.
This is the output i get with my code:
$ ./a.exe input4.txt floodfill 2 10 o
.............
.............
..XXX.....X..
..XXX.....X..
..XXX........
..XXX........
..XXXXXXX....
..XXXXXXX....
..XXXXXXX....
.............
Why do you iterate over the whole field in each recursion?
Normally, flood filling works as follows:
You have a specific starting point.
You fill this starting point with the colour intended
You check for each of the four (or 8, if you consider diagonals as well) neighbours, if they have the same colour as the starting point originally had; if so, you continue with recursively.
So an implementation might look like this:
void floodfill
(
std::vector<std::vector<char>>& v,
unsigned int x, unsigned int y, char r
)
{
char p = v[x][y];
v[x][y] = r;
if(x > 0 && v[x - 1][y] == p)
floodfill(v, x - 1, y, r);
if(x + 1 < v.size() && v[x + 1][y] == p)
floodfill(v, x + 1, y, r);
if(y > 0 && v[x][y - 1] == p)
floodfill(v, x, y - 1, r);
if(y + 1 < v[x].size() && v[x][y + 1] == p)
floodfill(v, x, y + 1, r);
}
Note that I did not check for the case of colour to fill being the same as the one of the starting pixel, neither did I initially check the range check of x and y. For efficiency, I wouldn't add these checks in the recursive function, but in a specific entry function starting the recursion, so they are done only once when needed and not needlessly repeated.
One option is to use recursion, as suggested by the other answer. However, personally I prefer avoiding recursion where it is not necessary. An alternative, is a queue-based approach.
void floodfill (std::vector<std::vector<char>>& v, unsigned int x, unsigned int y, char r) {
char init = v[x][y];
if (init == r) return; //We don't want to get caught in an endless loop.
if (x >= v.size() || y >= v[x].size) return; //Index out of bounds.
std::queue<std::pair<unsigned int, unsigned int>> q;
q.push(std::make_pair(x, y)); //Push the initial position into the queue.
v[x][y] = r; //Replace the initial point.
while (!q.empty()) {//Keep looking at relevant neighbours so long as there is something in the queue.
auto pt = q.front(); //Collect the first entry.
q.pop(); //Remove it, we don't want to keep processing the same point.
//Now add neighbours if they match our initial point.
if(pt.first > 0 && v[pt.first - 1][pt.second] == init)
q.push(std::make_pair(pt.first - 1, pt.second);
v[pt.first - 1][pt.second] = r; //Replace the value here to avoid pushing the same point twice.
if(pt.first + 1 < v.size() && v[pt.first + 1][pt.second] == init)
q.push(std::make_pair(pt.first + 1, pt.second);
v[pt.first + 1][pt.second] = r;
if(pt.second > 0 && v[pt.first][pt.second - 1] == init)
q.push(std::make_pair(pt.first, pt.second - 1);
v[pt.first][pt.second - 1] = r;
if(pt.second + 1 < v[pt.first].size() && v[pt.first][pt.second + 1] == init)
q.push(std::make_pair(pt.first, pt.second + 1);
v[pt.first][pt.second + 1] = r;
}
}
This gives you a BFS-like flood-fill pattern without recursion. Alternatively you could also use a stack instead of the queue, then the flood-fill would behave more like a DFS (much more similar to what the recursive pattern will do). It might even perform a little better than the queue, given the data structure is a little simpler.

How to find size of largest subset of a sub-sequence equal to a sum

I have this problem from hackerearth
Given an array of N integers, C cards and S sum. Each card can be used
either to increment or decrement an integer in the given array by 1.
Find if there is any subset (after/before using any no.of cards) with
sum S in the given array.
Input Format
First line of input contains an integer T which denotes the no. of
testcases. Each test case has 2 lines of input. First line of each
test case has three integers N(size of the array), S(subset sum) and
C(no. of cards). Second line of each test case has N integers of the
array(a1 to aN) seperated by a space.
Constraints
1<=T<=100 1<=N<=100 1<=S<=10000 0<=C<=100 1<=ai<=100
Output Format
Print TRUE if there exists a subset with given sum else print FALSE.
So this is basically a variation of the subset sum problem, but instead of finding out whether a given subset with a sum S exists, we need to find the largest subset from sequence index to N-1 that has a value of s and compare it's length with our C value to see if it is greater. If it is, then we have enough elements to modify the sum using our C cards, and then we print out our answer. Here is my code for that
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int N, S, C;
int checkSum(int index, int s, vector<int>& a, vector< vector<int> >& dP) {
if (dP[index][s] != -1)
return dP[index][s];
int maxNums = 0; // size of maximum subset array
for (int i = index; i < N; i++) {
int newSum = s - a[i];
int l = 0;
if (newSum == 0) {
l = 1;
} if (newSum > 0) {
if (i < (N-1)) { // only if we can still fill up sum
l = checkSum(i + 1, newSum, a, dP);
if (l > 0) // if it is possible to create this sum
l++; // include l in it
} else {
// l stays at 0 for there is no subset that can create this sum
}
} else {
// there is no way to create this sum, including this number, so skip it;
if (i == (N-1))
break; // don't go to the next level
// and l stays at 0
}
if (l > maxNums) {
maxNums = l;
}
}
dP[index][s] = maxNums;
return maxNums;
}
int main() {
int t;
cin >> t;
while (t--) {
cin >> N >> S >> C;
vector<int> a(N);
for (int i = 0; i < N; i++)
cin >> a[i];
vector< vector<int> > dP(N, vector<int>(S + C + 2, -1));
bool possible = false;
for (int i = 0; i <= C; i++) {
int l = checkSum(0, S-i, a, dP);
int m = checkSum(0, S+i, a, dP);
if ( (l > 0 && l >= i) || (m > 0 && m >= i) ) {
cout << "TRUE" << endl;
possible = true;
break;
}
}
if (!possible)
cout << "FALSE" << endl;
}
return 0;
}
So basically, 0 means it's not possible to create a subset equal to s from elements index to N-1, and -1 means we haven't computed it yet. And any other value indicates the size of the largest subset that sums up to s. This code isn't passing all the test cases. What's wrong?
You miss an else in following line
} if (newSum > 0) {
This make your program has an unexpected early break before updating maxNums by l in some cases.
For example, N=1, S=5, C=0, a={5}
Potential logic problem
You have limited the no. of card to be used to not exceed the subset size while the question never state you cannot apply multiple cards to same integers.
I mean l >= i and m >= i in
if ( (l > 0 && l >= i) || (m > 0 && m >= i) ) {
Seems you have logic flaw.
You need to find the shortest subset (with sum in range S-C..S+C) and compare it's size with C. If subset is shorter, it is possible to make needed sum.

Algorithm to build streets in a city with minimum cost?

Question details:
Rashof is the mayor of EMLand. EMLand consists of intersections and streets. There is exactly one path from each intersection to any of the other intersections. Intersections are denoted by positive intergers 1...n.
A construction company has offered Rashof to rebuild all streets of the EMLand, but Rashof can choose at most k of them to be rebuilt. The Construction company has offered a new length for each street which means after the street is rebuilt the length of the street changes.
Now Rashof as the mayor of the city must choose wisely so as to minimize sum of lengths of paths between all pairs of intersections.
Help Rashof!
Algorithm:
Notations: old edge length is L , new length is L' and set of edges E .
Count(C) number of edges(E') whose length is going to decrease i.e. L' < L
If C is less than or equal to K then
        take all edges(E') into account i.e. Update length of all such edges in E
Else
        1 . Sort all edges(E') based on (L'- L) in ascending order
        2 . Sort those edges(E'' ⊆ E') whose (L'-L) is same based on L' in descending order
        3.hoose 1st K edges(E''' ⊆ E') and update length of all such edges in E
Construct Graph G with Edge E and length L
Apply any shortest distance algorithm or DFS to find distance b/w each pair of node .
Implementation of above algorithm using priority queue and Dijkstra algorithm.
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
struct s{
int x;
int y;
int a;
int b;
int c;
};
const int MAX = 100000;
const long long INF = 100000000000000000;
vector< pii > G[MAX];
long long d[MAX];
void dijkstra(long long start) {
int u, v, i, c, w;
priority_queue< pii, vector< pii >, greater< pii > > Q;
for(i=0;i<MAX;i++){
d[i]=INF;
}
Q.push(pii(0, start));
d[start] = 0;
while(!Q.empty()) {
u = Q.top().second; // node
c = Q.top().first; // node cost so far
Q.pop(); // remove the top item.
if(d[u] < c) continue;
for(i = 0; i < G[u].size(); i++) {
v = G[u][i].first; // node
w = G[u][i].second; // edge weight
if(d[v] > d[u] + w) {
d[v] = d[u] + w;
//cout<<d[v];
Q.push(pii(d[v], v));
}
}
}
}
bool func(const s s1,const s s2) { return (s1.c < s2.c); }
bool func2(const s s1,const s s2) { return (s1.b < s2.b); }
int main() {
long long n, e, u, V, w,x,y,a,b,t,i,j,k,res,z=2;
s S;
vector<s> v;
map<pair<int,int>,int> m;
map<pair<int,int>,int>::iterator it;
cin>>t;
while(t--){
cin>>n>>k;
for(i = 1; i <= n; i++) G[i].clear();
v.clear();
m.clear();
for(i=1;i<n;i++){
cin>>x>>y>>a>>b;
if(b<a){
S.x = x;
S.y =y;
S.a=a;
S.b=b;
S.c=b-a;
v.push_back(S);
}
m[make_pair(x,y)]=a;
}
if(v.size()<=k){
for(i=0;i<v.size();i++){
m[make_pair(v[i].x,v[i].y)]=v[i].b;
}
it = m.begin();
for(;it!=m.end();++it){
u = it->first.first;
V = it->first.second;
w = it->second;
G[u].push_back(pii(V, w));
G[V].push_back(pii(u, w));
}
res = 0;
for(i=1;i<=n;i++){
dijkstra(i);
for(j= 1; j <= n; j++) {
if(i == j) continue;
if(d[j] >= INF) ;
else res+=d[j];
}
}
cout<<res/z<<"\n";
}
else{
sort(v.begin(),v.end(),func);
for(i=0;i<v.size();i++){
j = i;
while(v[i].c==v[j].c&&j<v.size())j++;
sort(v.begin()+i,v.begin()+j,func2);
i=j;
}
for(i=0;i<k;i++){
m[make_pair(v[i].x,v[i].y)]=v[i].b;
}
it = m.begin();
for(;it!=m.end();++it){
u = it->first.first;
V = it->first.second;
w = it->second;
G[u].push_back(pii(V, w));
G[V].push_back(pii(u, w));
}
res = 0;
for(i=1;i<=n;i++){
dijkstra(i);
for(j= 1; j <= n; j++) {
if(i == j) continue;
if(d[j] >= INF) ;
else res+=d[j];
}
}
cout<<res/z<<"\n";
}
}
return 0;
}
It passes only 2 test cases out of 9 test cases . Why this algorithm didn't work ?
or What are the modification should be done in this algorithm to get accepted ?
Reference:
Rashof, Mayor of EMLand
Traverse the tree/graph (eg nonrecursive DFS starting from any node) and count the number of times each edge is used (number of nodes on one side * number of nodes on the other side)
For each possible rebuild multiply delta by count
Sort
Profit
Notice that this is a tree, so, each edge connects two connected components.
Assume that we have edge connect between two connected components A and B, which contains n and m numbers of intersections, so, by decreasing the edge by x unit, we will decrease the total distance by n*m*x.
A---B---C----E
| |
| |
D---- -----F
Look at the graph above, edge between B and C connect two connected components, (A,B,D) and (C,E,F), decreasing the weight of this edge will decrease the distance between (A,B,D) and (C,E,F)
So, the algorithm is to select k edges, which has the largest n*m*x (if x is positive).