Unable to find a wrong answer testcase for spoj MMINPAID - algorithm

Problem link : http://www.spoj.com/problems/MMINPAID/
Getting WA on submitting.
I have used bfs to reach Nth node and calculating minimum cost for nodes in a path using bitmask. However after running on a huge number of testcases and comparing with an accepted solution, not able to find a failure testcase.
Code:
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int MAXN = 15, INF = 1 << 29;
struct node {
int c, p, r;
};
struct node data[MAXN][MAXN];
vector<int> g[MAXN];
int N, M, dist[MAXN][1 << 11];
int bfs() {
for (int i = 0; i < MAXN; i++)
for (int k = 0; k < (1 << 11); k++)
dist[i][k] = INF;
queue< pair< pair <int, int> , int > > q;
int v = 1, path = (1 << 1), cost = 0;
dist[v][path] = 0;
q.push(make_pair(make_pair(v, path), cost));
while (!q.empty()) {
int curv = q.front().first.first;
int curpath = q.front().first.second;
int curcost = q.front().second;
q.pop();
for (int i = 0; i < g[curv].size(); i++) {
int nv = g[curv][i];
int d1 = curcost + data[curv][nv].r;
int d2 = INF;
if (curpath & (1 << data[curv][nv].c)) {
d2 = curcost + data[curv][nv].p;
}
int d3 = min(d1, d2);
int npath = curpath | (1 << nv);
if (d3 < dist[nv][npath]) {
dist[nv][npath] = d3;
q.push(make_pair(make_pair(nv, npath), d3));
}
}
}
int res = INF;
for (int i = 0; i < (1 << 11); i++) {
res = min(res, dist[N][i]);
}
return res;
}
int main() {
scanf("%d %d", &N, &M);
for (int i = 0; i < M; i++) {
int a, b, c, p, r;
scanf("%d %d %d %d %d", &a, &b, &c, &p, &r);
g[a].push_back(b);
data[a][b] = (struct node) {c, p, r};
}
int ret = bfs();
if (ret == INF) printf("impossible\n");
else printf("%d\n", ret);
return 0;
}

I think the problem might be that your data[a][b] structure assumes there is at most a single road from a to b.
However, the problem states:
There may be more than one road connecting one city with another.

Related

CSES Dynamic Range Minimum Queries

https://cses.fi/problemset/task/1649
I'm solving this problem using Segment Trees and the solution I've written is
#include <bits/stdc++.h>
#define MAX 1000000001
using namespace std;
int n;
vector<int> tree;
int sum(int a, int b)
{
a += n;
b += n;
int s = INT_MAX;
while(a <= b) {
if (a % 2 == 1) s = min(s, tree[a++]);
if (b % 2 == 0) s = min(s, tree[b--]);
a>>=1;
b>>=1;
}
return s;
}
void update(int k, int change)
{
k += n;
tree[k] = change;
for(int i = k>>1; i >= 1; i>>=1) {
tree[i] = min(tree[2*i], tree[2*i+1]);
}
return;
}
int main()
{
int q;
cin >> n >> q;
n = pow(2, ceil(log2(n)));
tree.resize(2*n, INT_MAX);
for(int i = 0; i < n; i++) {
cin >> tree[i+n];
}
for(int i = n-1; i >= 1; i--) {
tree[i] = min(tree[2*i], tree[2*i+1]);
}
int type, a, b;
for(int i = 0; i < q; i++) {
cin >> type >> a >> b;
if (type == 1) {
update(a-1, b);
} else {
cout << sum(a-1, b-1) << endl;
}
}
return 0;
}
It works with first test case, but not with the second one. I've looked at other solutions online and they all look similar to mine. Please, help me spot the mistake.

Runtime error for large inputs for sorting ( quicksort)

This is a very simple program where the user inputs (x,y) coordinates and distance 'd' and the program has to find out the number of unrepeated coordinates from (x,y) to (x+d,y).
For eg: if input for one test case is: 4,9,2 then the unrepeated coordinates are (4,9),(5,9) and (6,9)(x=4,y=9,d=2). I have used a sorting algorithm as mentioned in the question (to keep track of multiple occurrences) however the program shows runtime error for test cases beyond 30. Is there any mistake in the code or is it an issue with my compiler?
For a detailed explanation of question: https://www.hackerearth.com/practice/algorithms/sorting/merge-sort/practice-problems/algorithm/missing-soldiers-december-easy-easy/
#include <stdio.h>
#include <stdlib.h>
int partition(int *arr, int p, int r) {
int x;
x = arr[r];
int tmp;
int i = p - 1;
for (int j = p; j <= r - 1; ++j) {
if (arr[j] <= x) {
i = i + 1;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
tmp = arr[i + 1];
arr[i + 1] = arr[r];
arr[r] = tmp;
return (i + 1);
}
void quicksort(int *arr, int p, int r) {
int q;
if (p < r) {
q = partition(arr, p, r);
quicksort(arr, p, q - 1);
quicksort(arr, q + 1, r);
}
}
int count(int A[],int ct) {
int cnt = 0;
for (int i = 0; i < ct; ++i) {
if (A[i] != A[i + 1]) {
cnt++;
}
}
return cnt;
}
int main() {
int t;
scanf("%d", &t);
long int tmp, y, d;
int ct = 0;
int i = 0;
int x[1000];
int j = 0;
for (int l = 0; l < t; ++l) {
scanf("%d%d%d", &tmp, &y, &d);
ct = ct + d + 1; //this counts the total no of coordinates for each (x,y,d)
for (int i = 0; i <= d; ++i) {
x[j] = tmp + i; //storing all possible the x and x+d coordinates
j++;
}
}
int cnt;
int p = ct - 1;
quicksort(x, 0, p); //quicksort sorting
for (int l = 0; l < ct; ++l) {
printf("%d ", x[l]); //prints sorted array not necessary to question
}
cnt = count(x, ct); //counts the number of non-repeated vertices
printf("%d\n", cnt);
}
The problem was the bounds of the array int x[1000] is not enough for the data given below.

Special minimum spanning tree

There is a node that can only get one line, I use both kruskal and prim, but the judger said TLE(Time Limit Exceed).
Then I will describe the question. There are many computers, we need to connect all of them, we give the cost of connection between different computers, also we give the special number of computer which can be only connected by one line. Finally, we guarantee there is a answer and there is no Self-Loop, but there may have multiple edge which have different weight between same node.
Here is my kruskal code, it's TLE.
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct edge{
int start;
int end;
int weight;
}Edge;
int special = 0;
int edgenum;
Edge _edge[600005];
int i, j, k;
int counter = 0;
bool Cmp(const edge &a, const edge &b){
return a.weight < b.weight;
}
int getEnd(int vends[], int i){
while(vends[i] != 0)
i = vends[i];
return i;
}
void kruskal(){
int p1, p2, m, n, ans = 0;
int vends[10005] = {0};
sort(_edge, _edge+counter, Cmp);
for(i = 0; i < edgenum; ++i){
p1 = _edge[i].start;
p2 = _edge[i].end;
if ((p1 == k || p2 == k) && special)
continue;
m = getEnd(vends, p1);
n = getEnd(vends, p2);
if(m != n){
if (p1 == k || p2 == k)
special = 1;
vends[m] = n;
ans += _edge[i].weight;
}
}
cout << ans << endl;
}
int main(){
int n, m;
cin >> n >> m >> k;
edgenum = m;
while(m--){
int a, b, c;
cin >> a >> b >> c;
_edge[counter].start = a; //Get the Edge
_edge[counter].weight = c;
_edge[counter++].end = b;
// _edge[counter].start = b;
// _edge[counter].weight = c;
// _edge[counter++].end = a;
}
kruskal();
}
Here is my Prim, but also TLE:
#include <iostream>
using namespace std;
typedef char VertexType;
typedef struct node{
int adjvex = 0;
int weight = INT32_MAX;
struct node *next = NULL;
}Node;
typedef struct vnode{
VertexType data;
Node *firstnode = NULL;
}Vnode;
Vnode node[10005];
int VNUM;
int n, m, k;
int lowcost[10005] = {0};
int addvnew[10005]; //未加入最小生成树表示为-1,加入则为0
int adjecent[10005] = {0};
bool is_special = false;
int flag;
void prim(int start){
long long sumweight = 0;
int i, j;
Node *p = node[start].firstnode;
for (i = 1; i <= VNUM; ++i) { //重置
addvnew[i] = -1;
}
while (p->next != NULL){
if (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])
lowcost[p->adjvex] = p->weight;
p = p->next;
}
if (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])
lowcost[p->adjvex] = p->weight;
addvnew[start] = 0;
// adjecent[start] = start;
if (start == k) {
is_special = true;
flag = 1;
}
for (i = 1; i < VNUM; ++i) {
int min = INT32_MAX;
int v=-1;
for (j = 1; j <= VNUM; ++j) { //Find the min
if (addvnew[j] == -1 && lowcost[j] < min && lowcost[j] != 0){
min = lowcost[j];
v = j;
}
}
if (v != -1){ //if min is found
if (flag == 1){
for (int l = 0; l < 10005; ++l) {
lowcost[l] = 0;
}
flag = 0;
}
addvnew[v] = 0;
sumweight += min;
p = node[v].firstnode;
while(p->next != NULL){
if (is_special && p->adjvex == k){ //If find the special node
p = p->next;
continue;
}
if(addvnew[p->adjvex] == -1 && (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])){ //如果该点未连接
lowcost[p->adjvex] = p->weight;
}
p = p->next;
}
if (!(is_special && p->adjvex == k))
if(addvnew[p->adjvex] == -1 && (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])){
lowcost[p->adjvex] = p->weight;
}
}
}
cout << sumweight << endl;
}
int main(){
cin >> n >> m >> k;
VNUM = n;
while (m--){
int a, b, c;
cin >> a >> b >> c;
Node *p = (Node*)malloc(sizeof(Node));
p->adjvex = b;
p->weight = c;
p->next = node[a].firstnode;
node[a].firstnode = p;
Node *q = (Node*)malloc(sizeof(Node));
q->adjvex = a;
q->weight = c;
q->next = node[b].firstnode;
node[b].firstnode = q;
}
prim(k);
}
I don't know how to modify the both code, I try my best, thank you

Dijkstra running slow

There is a problem at Spoj called HIGHWAYS, that is basically to find the shortest path between 2 given cities.
The first time I solved it, I used Dijkstra algorithm... I got it right, although the code was kind of big, so I decided to redo it with smaller code (that obviously acts the same way), but it's getting Time Limit Exceeded.
I'd like to know what difference between them is making this TLE to happen.
The input is like this:
n //number of test cases
c e s e //number of cities (from 1 to c), number of edges, start and end cities
c1 c2 w //e lines, each with connection between c1 and c2 with weight w
Here are the long code (Accepted):
#include <bits/stdc++.h>
using namespace std;
#define si(n) scanf("%d", &n)
#define INF 99999
int d[100010];
struct edge {
int v, weight;
edge(int a, int w) {
v = a;
weight = w;
}
bool operator < (const edge & o) const {
return weight > o.weight;
}
};
struct vertex {
int value;
vector <edge> adj;
vertex() {
adj.clear();
}
vertex(int val) {
value = val;
adj.clear();
}
void add(edge a) {
adj.push_back(a);
}
};
struct graph {
vertex v[100010];
void add_v(int val) {
vertex a(val);
a.adj.clear();
v[val] = a;
}
void add_a(int v1, int v2, int p) {
v[v1].add(edge(v2, p));
v[v2].add(edge(v1, p));
}
void dijkstra(int n, int f) {
for(int i = 0; i <= f; i++ ) d[i] = INF;
priority_queue < edge > Q;
d[n] = 0;
int current;
Q.push(edge(n, 0));
while (!Q.empty()) {
current = Q.top().v;
Q.pop();
for (int i = 0; i < v[current].adj.size(); i++) {
edge a = v[current].adj[i];
if (d[a.v] > d[current] + a.weight) {
d[a.v] = d[current] + a.weight;
Q.push(edge(a.v, d[a.v]));
}
}
}
}
};
int main(){
int cases;
si(cases);
int v, a, ini, fim;
int v1, v2, w;
while(cases--){
si(v); si(a);
si(ini); si(fim);
graph g;
for(int i = 1; i <= v; i++){
g.add_v(i);
}
for(int i = 0; i < a; i++){
si(v1); si(v2); si(w);
g.add_a(v1, v2, w);
}
g.dijkstra(ini, v+1);
int dist = d[fim];
if(dist < 0 || dist >= INF) printf("NONE\n");
else printf("%d\n", dist);
}
}
Here is the short one (Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
struct edge{
int v, w;
edge(){}
edge(int a, int b){v = a; w = b;}
};
bool operator < (edge a, edge b) {return a.w < b.w;}
const int INF = INT_MAX;
typedef vector<vector<edge> > graph;
typedef priority_queue<edge> heap;
int d[100020];
void Dijkstra(graph G, int length, int s){
for(int i = 1; i <= length; i++) d[i] = INF;
edge base;
base.v = s;
base.w = d[s] = 0;
heap H;
H.push(base);
while(!H.empty()){
int current = H.top().v;
H.pop();
for (int i = 0; i < G[current].size(); i++) {
edge a = G[current][i];
if (d[a.v] > d[current] + a.w) {
d[a.v] = d[current] + a.w;
H.push(edge (a.v, d[a.v]));
}
}
}
}
int main(){
int cases;
int n, m, s, e;
int v1, v2, w;
scanf("%d", &cases);
while(cases--){
scanf("%d %d %d %d", &n, &m, &s, &e);
graph G(n + 1);
for(int i = 0; i < m; i++){
scanf("%d %d %d", &v1, &v2, &w);
G[v1].push_back(edge(v2, w));
G[v2].push_back(edge(v1, w));
}
Dijkstra(G, n, s);
if(d[e] != INF) printf("%d\n", d[e]);
else printf("NONE\n");
}
}
The difference is in how you control the priority queue. In the long version, you take the edges with a small weight first, which enables you to find the optimum earlier and cut many possible paths short:
bool operator < (const edge & o) const {
return weight > o.weight;
}
In the short version, you have the behaviour (accidentially?) reversed and always take the edge with the greatest weight, which means that you effectively probe all possible paths.
bool operator < (edge a, edge b) {return a.w < b.w;}
Change the inequality operator and both versions will run equally fast.
The containers of STL are slow. Avoid using vector if necessary.
here is my dij:
class graph
{
public :
int head[N],next[M],node[M];
int dist[M];
int tot;
void init()
{
tot = 0;
CLR(head,-1);
}
void add(int x,int y,int z = 1)
{
node[tot] = y;
dist[tot] = z;
next[tot] = head[x];
head[x] = tot++;
}
graph() {init();}
} g;
int dist[N]; ///the distance
///src means source. ter is optional, it means terminal
void dij(int src, graph &g, int ter=-1)
{
memset(dist,0x3f,sizeof(dist)); ///init d[i] as a very large value
dist[src] = 0;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > pq;
pq.push(make_pair(dist[src],src));
while(!pq.empty())
{
int x = pq.top().second;
int d = pq.top().first;
if(d != dist[x])continue;
if(x == ter)return ;
for(int i = g.head[x] ; ~i ; i = g.next[i])
{
int y = g.node[i];
if(d+g.dist[i]<dist[y])
{
dist[y] = d + g.dist[i];
pq.push(make_pair(dist[y],y));
}
}
}
}

What's wrong with my implementation of bellman-ford?

i am clueless as to what is wrong with this piece of code.
its not working as expected.
its expected to display the shortest path from vertex 1 to N.
but its failing on a lot of cases.
one such case is
3 1
1 2 1
it shows the answer as
1 25 -1 3
which is wrong...
any help would be appreciated.
Thanks.
#include <iostream>
#include <cstdio>
#include <vector>
#include <list>
using namespace std;
struct Edge{
int I, W;
};
vector <int> dist;
vector <int> parent;
bool bellman_ford(const vector< vector <Edge> > &graph, int n){
dist[1] = 0;
parent[1] = 0;
for(int k = 1; k <= n-1; k++){
for(int i = 1; i <= n; i++){
int len = graph[i].size();
for(int j = 0; j < len; j++){
int v = graph[i][j].I;
int w = graph[i][j].W;
if(dist[v] > dist[i] + w){
dist[v] = dist[i] + w;
parent[v] = i;
}
}
}
}
for(int i = 1; i <= n; i++){
int len = graph[i].size();
for(int j = 0; j < len; j++){
int v = graph[i][j].I;
int w = graph[i][j].W;
if(dist[v] > dist[i] + w){
return false;
}
}
}
return true;
}
int main(void){
int n, m, x, y, w;
scanf("%d%d", &n, &m);
dist.resize(n+1, 10000000);
parent.resize(n+1, -1);
vector < vector <Edge> > graph (n+1, vector <Edge> (0)) ;
for(int i = 0; i < m; i++){
scanf("%d%d%d", &x, &y, &w);
Edge a, b;
a.I = y;
b.I = x;
a.W = b.W = w;
graph[x].push_back(a);
graph[y].push_back(b);
}
if(bellman_ford(graph, n)){
int k = n;
vector<int>ans;
ans.push_back(n);
while(parent[k] != 0){
ans.push_back(parent[k]);
k = parent[k];
}
for(int i = ans.size()-1; i >= 0; i--){
printf("%d ", ans[i]);
}
printf("\n");
}
}
For the input case 3 1 1 2 1 you have a graph of 3 vertices, but the graph has only a single edge (1->2):
(1)<~~>(2) (3)
so the vertex numbered 3 (n) is never reached. The parent node of 3 is set to initial value -1, your loop searches for 0. You have no check if there actually is a path from a source to its target or not at all. The output is correct until -1:
3 - target
-1 - target has no parent, the loop should stop
25 - *garbage* (UB)
1 - *garbage* (UB)

Resources