Wrong answer on SPOJ FASTFLOW? - c++

Can anyone help me out with this problem I am trying it for days . I am getting wrong answer every time . I used Edmonds - Karp method ... Here is my code :
#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#define MAXX 900000000
using namespace std;
long int capacity[5005][5005] ;
int graph[5005][5005] , v[5005] , from[5005] ;
//Calculating Max Flow using Edmond karp
int Max_Flow(int s , int t)
{ queue<int>Q ;
// Bfs to get the paths from source to sink
Q.push(s) ;
v[s] = 1 ;
int r ;
long long int min ;
while(!Q.empty())
{ int p = Q.front() ;
Q.pop();
r = 0 ;
for(int j = 0 ; graph[p][j]!=0 ; j++)
{
if(!v[graph[p][j]]&&capacity[p][graph[p][j]])
{ Q.push(graph[p][j]) ; from[graph[p][j]] = p ;
v[graph[p][j]] = 1 ;
if(graph[p][j]==t)
{ r = 1 ; break ; }
}
}
if(r==1)
break ;
}
r = t ;
min = MAXX ;
// Caculating the minimum capacity over the path found by BFS
while(from[r]!=0)
{
if(min>capacity[from[r]][r])
min = capacity[from[r]][r] ;
r = from[r] ;
}
r = t ;
//Subtracting the min capacity found over the path
while(from[r]!=0)
{
capacity[from[r]][r]-=min;
capacity[r][from[r]]+=min;
r = from[r] ;
}
if(min==MAXX)
return 0;
else
return min;
}
int main()
{
int t , n , s , c , i , j , k , a , b , p = 0 ;
unsigned long long int flow , r ;
memset(capacity,0,sizeof(capacity));
memset(from,0,sizeof(from));
memset(graph,0,sizeof(graph));
memset(v,0,sizeof(v));
scanf("%d%d",&n,&c);
for(i = 0 ; i<c ; i++)
{
scanf("%d%d%d",&a,&b,&k);
if(b!=a)
{
capacity[a][b]+=k ;
capacity[b][a]+=k ;
j = 0 ;
r = 0 ;
while(graph[a][j]!=0)
{ if(graph[a][j]==b)
{ r = 1 ; break ; }
j++;
}
if(!r) graph[a][j] = b ;
j = 0 ;
r = 0 ;
while(graph[b][j]!=0)
{ if(graph[b][j]==a)
{ r = 1 ; break ; }
j++;
}
if(!r) graph[b][j] = a ;
}
}
flow = 0 ;
r = 1 ;
while(r)
{ flow+=r ;
r = Max_Flow(1,n) ;
memset(from,0,sizeof(from));
memset(v,0,sizeof(v));
}
printf("%lld\n",flow-1);
return 0;
}
As the problem statement says : "Note that it is possible for there to be duplicate edges, as well as an edge from a node to itself" . So I ignored the self loops and added the capacity of repeated edges in the 'capacity' array corresponding to those nodes . I created a 'graph' and performed BFS from source to sink to get paths until all the paths have been augmented . I summed up all min values found and printed the answer ... Can anyone explain why wrong answer ?

Suppose you had a simple graph with a single edge between start and end with capacity 1 billion.
As your MAXX < 1 billion, when you run the Max_Flow you would find a flow of MAXX and incorrectly conclude that this meant there was no augmenting path found.
If this is the case, then simply try replacing
#define MAXX 900000000
with
#define MAXX 1100000000
and the program might pass...

Related

The program doesn't give any output on VS Code if I use 'const int ' and assign it a big value like 1e6 [duplicate]

This question already has answers here:
C++ program is not giving output involving large array
(5 answers)
Why should I not #include <bits/stdc++.h>?
(9 answers)
Closed 9 months ago.
#include <bits/stdc++.h>
using namespace std ;
int main () {
int n ;
cin >> n ;
int a [n] ;
for ( int i = 0 ; i < n ; i++ ) {
cin >> a [i] ;
}
const int N = 1e6 + 2 ; // This is where the problem is...
bool check [N] ;
for ( int i = 0 ; i < N ; i++ ) {
check [i] == 0 ;
}
for ( int i = 0 ; i < N ; i++ ) {
if ( a [i] >= 0 ) {
check [a[i]] = 1 ;
}
}
int ans = -1 ;
for ( int i = 0 ; i < N ; i++ ) {
if ( check [i]==0 ) {
ans = i ;
break;
}
}
cout << ans ;
return 0 ;
}
When I run the above program in the VS Code terminal I get no output... :
PS C:\Users\LENOVO\Desktop\C++ Programs> cd "c:\Users\LENOVO\Desktop\C++ Programs\" ; if ($?) { g++ smallest_positive_missing_number.cpp -o smallest_positive_missing_number } ; if ($?) { .\smallest_positive_missing_number }
6
0 -9 1 3 -4 5
PS C:\Users\LENOVO\Desktop\C++ Programs>
First, stop using VLA because it is NOT supported in c++ standard. Use vector or new instead.
int *a = new int[n];
bool *check = new bool[N];
And use them just like a normal array.
As for your problem, it is clearly caused by VLA with big size, and it will run perfectly once you switch to new or vector.
Edit:
However, like the comment below said, the array cited this problem is not VLA. They just act the same and mess up your stack.

Find numbers which are a product of two 3 digit numbers (Project Euler #4)

The original question goes like this , we have to find the smallest palindrome less than a given number(given by the user ) which has to be a multiple of two three digit numbers . I got the palindrome part sorted out but am stuck on the "multiple" part . I was able to sort out the prime numbers but cant figure out
anything else.
EDIT:- Seems I wasn't clear in my question so here's an example 101101 is a palindrome and also a product of two three digit numbers (of 143 and 107 )which also happens to be the smallest palindrome of this type
Here goes my source code
#include <iostream>
using namespace std;
int main(){int t ;
cin >> t ;
for (int a0=0 ; a0<t ; a0++){int n ;
cin >> n ;
while(n>101101){
int num , rev = 0 , dig ;
num = n ;
while(num != 0 ){
dig = num%10;
rev= (rev*10) + dig ;
num = num /10;
}
if (rev==n ){
cout << n ;
break ;
}
else {
n= n -1;
}}}}
Here goes the code which has a function which will check that whether the palindrome number is a product of two three digit numbers.
#include <iostream>
using namespace std;
bool checkMultiple(int num)
{
for(int i=100 ; i<=999; i++)
{
for(int j=100 ; j<=999; j++)
{
if((i*j) == num)
{
// cout<<i<<"*"<<j<<"="<<num<<endl;
return true;
}
}
}
return false;
}
int main()
{
int t ;
cin >> t ;
for (int a0=0 ; a0<t ; a0++)
{
int n ;
cin >> n ;
while(n>101101)
{
int num , rev = 0 , dig ;
num = n ;
while(num != 0 )
{
dig = num%10;
rev= (rev*10) + dig ;
num = num /10;
}
if (rev==n )
{
bool palindrome = checkMultiple(n);
if(palindrome)
{
cout << n ;
break ;
}
}
else
{
n= n -1;
}
}
}
system("pause");
return 0;
}
Since you have figured out the palindrome part, try this for the multiple part:
1.check if it is a multiple of a 3 digit num (% operator)
2.if you get one (call n1) ,run the loop again for another similar 3 digit num other than n1, then you've got your palindrome.
3.then run another outtermost loop which executes till you get your result, checking each possible palin as mentioned above.

Algorithm for finding a plus sign in a grid

I have this problem of finding the largest 'PLUS' in a given grid.
For example, If I have the following grid:
..#..
..#.#
#####
..#.#
..#..
The largest 'PLUS' in it would be of size 3 . Similarly, for
..#
#.#
#.#
The answer would be 1 as no particular 'PLUS' exists (except the origin of course).
The algorithm I have in mind goes like this:
Find a location with # and with # on all its 4 directions. Like (2, 2) in figure 1.
Use Breadth First Search strategy to add all its neighbors in the queue along with the direction they lie in (left, right, up, down).
Keep visiting and adding neighbors pertaining to that particular direction.
Repeat until you encounter a . or run out of bounds.
While doing all this, we can maintain an array which can maintain the count of # occurring in each direction.
Code:
int x[4] = {-1,0,1,0} ;
int y[4] = {0,1,0,-1} ;
int n, dir[4], result ;
char adj[2001][2001] ;
int bfs(int sx, int sy) {
queue < pair <int, pair <int, int> > > q ;
q.push(make_pair(0, make_pair(sx+x[0], sy+y[0]))) ;
q.push(make_pair(1, make_pair(sx+x[1], sy+y[1]))) ;
q.push(make_pair(2, make_pair(sx+x[2], sy+y[2]))) ;
q.push(make_pair(3, make_pair(sx+x[3], sy+y[3]))) ;
while (!q.empty()) {
pair <int, pair <int, int> > curr = q.front() ;
q.pop() ;
int current_direction = curr.first ;
int current_x = curr.second.first + x[current_direction] ;
int current_y = curr.second.second + y[current_direction] ;
if (current_x>=0&&current_x<n&&current_y>=0&&current_y<n) {
if (adj[current_x][current_y] == '#') {
++dir[current_direction] ;
q.push(make_pair(current_direction, make_pair(current_x, current_y))) ;
}
else
break ;
}
else
break ;
}
result = *min_element(dir, dir+4) ;
return result ;
}
int main() {
int t ; scanf("%d", &t) ;
while (t--) {
scanf("%d", &n) ;
for (int i = 0; i < n; i++)
cin >> adj[i] ;
bool flag = true ;
int max_plus = 0 ;
for (int i = 1; i < n - 1; i++)
for (int j = 1; j < n - 1; j++) {
if (adj[i][j] == '#' && adj[i-1][j] == '#' \\
&& adj[i][j+1] == '#' && adj[i+1][j] == '#' \\
&& adj[i][j-1] == '#') {
// cout << i << " " << j << endl ;
flag = false ;
memset(dir, 2, sizeof(dir)) ;
max_plus = max(max_plus, bfs(i, j)) ;
}
}
if(flag)
cout << "1" << endl ;
else
cout << max_plus << endl ;
}
return 0 ;
}
This code seems to give a weird output (33686019) for figure 1.
I can't seem to find the error I'm running into with respect to the code. Also, if there is something wrong with the algorithm I have, I'd love some advice.
I don't exactly know what is wrong with your code and whether your algorithm is correct or not. But I don't think you need BFS to solve this problem. Create 4 matrices that keeps the number of consecutive #s up, down, left and right of each #:
..#..
..#.#
#####
..#.#
..#..
up
..0..
..1.0
00201
..3.2
..4..
down
..4..
..3.2
00201
..1.0
..0..
right
..0..
..0.0
43210
..0.0
..0..
left
..0..
..0.0
01234
..0.0
..0..
now create a matrix by keeping the minimum of 4 matrices for each element
min
..0..
..0.0
00200
..0.0
..0..
The answer is maximum of the min matrix.
suppose you want to count how many consecutive '#'s are behind each '#'.
for i from 0 to str.length
if s[i]=='#':
if s[i-1]=='#': // beware of i==0
dp[i] = dp[i-1]+1
else
dp[i] = 0
str ..##.###...##...
dp ..01.012...01...

I have to check whether all the elements of an array is equal to one or not...and use it as a while condition...how do i do that?

I have an array....I need to check whether all its elements are equal to one and pass this as a while condition. That is...my code should be executed till all the members of the array becomes one.
My code goes like this:
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int ele[10];int crd[10];int dist[10] ; int fid[10] ;
int a; int i ; int j;int k = 0,l=0 ; // a is number of villages
cin>> a ;
for(i = 0;i<a;i++){
cin>>ele[i] ;
}
for(i=0;i<a;i++){
cin>>crd[i] ;
}
for(k = 0;k<a;k++){
while(ele[k]= 1){
for(i=0;i<a;i++){
if(ele[i] == 0 && ele[i+1] == 1 ){
dist[l] = std::abs(crd[i+1] - crd[i]) ;
fid[l] = i ;
l++ ;
}else if(ele[i]==1 && ele[i+1] == 0 ){
dist[l] = std::abs(crd[i+1] - crd[i]) ;
fid[l] = i + 1;
l++ ;
// ele[i+1] = 1
}
}
for(i=0;i<l;i++){
cout<<fid[i] ;
}
for(i=0;i<l;i++){
cout<<dist[i]<<" " ;
}
for(i=0;i<l;i++){
if(dist[0]>dist[i]){
swap(dist[0],dist[i]) ;
ele[fid[i]] = 1 ;
//swap()
}else if(l=1){
ele[fid[0]] = 1 ;
}
}
for(i=0;i<a;i++){
cout<<ele[i]<<endl ;
}
cout<<dist[0] ;
}
}
}
The error lies in this statement.
while(ele[k]= 1)
It will always return true as ele[k] is assigned the value 1 which is not 0 leading to an infinite loop. Also there is no need to include so many for loops and while loops. Your condition should be something like:
k=0;
while(k < a)
{
ele[k] = 1;
k++;
}
And there is no need of any for loops at all. Your question does not match with the code you have written. If indeed, you mean to simply replace all values of ele[k] with 1, the above code I have provided should suffice and there would be no use of any other statements in your code. Primarily I believe you should study up while loops and understand how they work essentially. Also, no matter what code the error is in, you should never post unformatted code.

3-opt optimization code for TSP

I have this code (tsp problem) that works for the 2-opt optimization and i'd like to change it for a 3-opt optimization. I know i must add a for, but don't really understand the range of the third for. Can you help me?
double bestDecrement = tsp.infinite;
// intial and final position are fixed (initial/final node remains 0)
for ( uint a = 1 ; a < currSol.sequence.size() - 2 ; a++ )
{
int h = currSol.sequence[a-1];
int i = currSol.sequence[a];
for ( uint b = a + 1 ; b < currSol.sequence.size() - 1 ; b++ )
{
int j = currSol.sequence[b];
int l = currSol.sequence[b+1];
double neighDecrement = - tsp.cost[h][i] - tsp.cost[j][l] + tsp.cost[h][j] + tsp.cost[i][l] ;
if ( neighDecrement < bestDecrement )
{
bestDecrement = neighDecrement;
move.from = a;
move.to = b;
}
}
}
Basically you are looking for 3 edges to remove and then reinsert. So for example:
for ( uint a = 1 ; a < currSol.sequence.size() - 3 ; a++ )
...
for ( uint b = a + 1 ; b < currSol.sequence.size() - 2 ; b++ )
...
for ( unit c = b + 1 ; c < currSol.sequence.size() - 1 ; c++)
...
The trickier part is determining the new costs, since there are a few feasible reinsertions (as opposed to just one in 2-opt).