Page 1 of 2

### 10917 - Walk Through the Forest

Posted: Mon Oct 03, 2005 9:43 pm
I have collected Input for this problem from website.
But I can not check it.Because I have used long type array.
Which is not suported by my visual c++ compiler.
I am waiting.

Posted: Tue Oct 04, 2005 8:55 am
Will I use dynamic variable?.
If not, Clarify me through example how to use adjacency list.
When M=500000(Five lucks)then what will be hapen.
Because the limit of value of M was not declared.
My another question is : "Can I use long array in uva judge?"

Posted: Tue Oct 04, 2005 10:15 am
method for representation of graph with adjancey list is well-known and easy fomular:

you can find them in many books, or internet pages.

TISARKER wrote:My another question is : "Can I use long array in uva judge?"
Sure, memory is enough.

and I didn't knew that there exist a compiler which doesn't support 1000 * 1000 32-bit-integer marix. BTW, In this problem, i guess that the most of input graphs are sparse graph, so I recommend you to use adjency lists/array rather than matrix.

Posted: Fri Oct 07, 2005 7:02 pm
Thank u very much.

Posted: Fri Oct 07, 2005 7:03 pm
Thank u very much.

### 10917 - A Walk Through the Forest

Posted: Thu Jan 19, 2006 10:51 pm
plz clarify me something, i am getting tle. can this problem be solved using backtracking(dfs) within time-limit? output can be at most 2147483647. simply the program below run for near 3 sec in my computer

Code: Select all

``````void main()
{
int i;
for(i = 0; i < 2147483647; ++i)
;
}``````
which algorithm should be used for this problem with a better runtime? i used backtracking(dfs), i used adjacancy list, i pruned whenever a node is found before with a short distance. and one more question, can there be such any input, where a node is numdered with a value greater than n or less than 1? (n is the total number of nodes)

Posted: Thu Jan 19, 2006 11:09 pm
You can use Dijkstra to find a subgraph in which Jimmy may walk, then use dynamic programming to count paths in it.

Posted: Thu Jun 08, 2006 9:20 am
why am i getting wa? i used dijkstra to find distance to all vertices. then i ran the following DP
n_path(dest) = summation of n_path(v), where v is adjacent to dest and distance[v] == distance[dest] - weight[v,dets], is this correct?

Code: Select all

``````#include <stdio.h>
#include <string.h>
#include <ctype.h>

struct
{
int d;
} list;

bool visited;

int extractMin()
{
int i, min = 2147483646, index = -1;
for(i = 0; i < n; ++i)
if(visited[i] == false && dist[i] != -1 && dist[i] < min)
{
min = dist[i];
index = i;
}
return index;
}

void dijkstra()
{
int i, u, v;
memset(dist, -1, sizeof(dist));
memset(visited, false, sizeof(visited));
dist = 0;
for(;;)
{
u = extractMin();
if(u != -1)
visited[u] = true;
else
break;
for(i = 0; i < n_adj[u]; ++i)
{
if(visited[v] == false && (dist[v] == -1 || dist[v] > dist[u] + list[u][i].d))
dist[v] = dist[u] + list[u][i].d;
}
}
}

int n_path(int u)
{
if(u == 0)
return 1;
if(memory[u] != -1)
return memory[u];
int i, count = 0, v;
for(i = 0; i < n_adj[u]; ++i)
{
if(dist[v] != -1 && dist[v] == dist[u] - list[u][i].d)
count += n_path(v);
}
return memory[u] = count;
}

bool exit(char s[], int &m)
{
int i, count = 0, prev = ' ';
for(i = 0; s[i]; ++i)
{
if(isdigit(s[i]) && !isdigit(prev))
++count;
prev = s[i];
}
if(count == 1)
{
sscanf(s, "%d", &n);
if(n == 0)
return true;
}
else if(count == 2)
{
sscanf(s, "%d%d", &n, &m);
return false;
}
else
n /= 0;
return false;
}

void main()
{
int m, x, y, d;
char s;
for(;;)
{
scanf(" %[^\n]", s);
if(exit(s, m))
break;
while(m--)
{
scanf("%d%d%d", &x, &y, &d);
--x;
--y;
}
dijkstra();
memset(memory, -1, sizeof(memory));
printf("%d\n", n_path(1));
}
}``````
i read the explanation of the page above, but i dont understand is there any necessity of topological sort?

Posted: Mon Aug 28, 2006 2:31 am
Try this:
Let d(u) be the distance between vertice u and 2.
then f(u) = sum of f(v) such that u,v are adjacent and d(v)<d(u)
where f(u) is the number of path from u to 2

### Why WA...

Posted: Thu May 10, 2007 7:18 pm

Code: Select all

``cut after AC``

Posted: Thu May 10, 2007 8:49 pm
Try the cases.

Input:

Code: Select all

``````6 11
1 6 2995
6 3 4827
3 1 32391
1 3 153
3 5 12382
5 4 18716
4 3 19895
3 6 21726
6 1 1869
1 5 25667
5 2 17035
10 8
1 4 16803
4 8 6286
8 1 28531
1 10 10722
10 3 22946
3 8 24230
8 6 30570
6 2 19832
0``````
Output:

Code: Select all

``````3
2``````
Hope these help.

Posted: Fri May 11, 2007 7:55 am
Jan , thanks for help me.Your data really helped me.

### lots of WA

Posted: Fri May 18, 2007 11:24 pm
What i've done is:

1. Find shortest path from 2 to all vertex using dijkstra
2. build another di graph with edges (u,v) such that d > d[v] in the original graph. that is length of any path from v to 2 is shorter than length of any path from u to 2;
3. count the number of paths from 1 to 2 in the new graph using BFS.

I'm getting WA with this approach. This code passes the inputs given in this post.Can some1 give me some I/O , suggetions plz.

Code: Select all

``````

#include <stdio.h>
#include <vector>
#include <queue>
#include <functional>
#include <string.h>

using namespace std;

#define MAXN	1005
#define INF		999999999

typedef struct node_
{
int u,cost;
} node_;

bool operator < (node_ a,node_ b){ return a.cost > b.cost; }
bool operator > (node_ a,node_ b){ return a.cost < b.cost; }
bool operator == (node_ a,node_ b){ return a.cost == b.cost; }

int v,E;
int d[MAXN],path[MAXN];
bool visited[MAXN];
priority_queue <node_> PQ;

void dijkstra(int s)
{
int i;
node_ u,next;

for( i = 1; i <= v; i++ )
{
d[i] = INF;
visited[i] = false;
}

d[s] = 0;
u.u = s,u.cost = 0;
while(!PQ.empty()) PQ.pop();
PQ.push(u);

while(!PQ.empty())
{
u = PQ.top();
PQ.pop();

if( visited[u.u] ) continue;
visited[u.u] = true;

for( i = 0; i < adj[u.u].size(); i++ )
{

if( !visited[next.u] )
{
if( d[next.u] > d[u.u] + next.cost )
{
d[next.u] = d[u.u] + next.cost;
PQ.push(next);
}
}
}

}
}

void rebuildGraph()
{
int i,j;
node_ u;

for( i = 1; i <= v; i++ )
{
for( j = 0; j < adj[i].size(); j++ )
{
if( d[i] > d[u.u] ) newAdj[i].push_back(u.u);
}
}
}

void countPath()
{
int i,u,next;
queue <int> Q;
memset(visited,false,sizeof(visited));
memset(path,0,sizeof(path));
path = 1,visited = true;
Q.push(1);

while(!Q.empty())
{
u = Q.front();
Q.pop();

for( i = 0; i < newAdj[u].size(); i++ )
{
if( !visited[next] )
{
visited[next] = true;
path[next] = path[u];
Q.push(next);
}
else path[next] += path[u];
}
}
}

int main()
{
int i,m,n,w;
node_ push;

while(scanf("%d",&v) == 1 && v)
{
scanf("%d",&E);

for( i = 1; i <= v; i++ ) adj[i].clear();

for( i = 0; i < E; i++ )
{
scanf("%d %d %d",&m,&n,&w);
push.u = n;push.cost = w;
}

dijkstra(2);
rebuildGraph();
countPath();
printf("%d\n",path);
}

return 0;
}

``````

Posted: Fri Feb 01, 2008 8:52 am
Sclo wrote:
Try this:
Let d(u) be the distance between vertice u and 2.
then f(u) = sum of f(v) such that u,v are adjacent and d(v)<d(u)
where f(u) is the number of path from u to 2
I have implemented this & getting WA.
This is my function :

Code: Select all

``````int f(int u)
{
int cnt=0,v;
if(u==2)
return 1;
if(ct[u]>=0)
return ct[u];
for(v=1;v<=n;v++)
if(mat[v][u]<inf && dist[v]<dist[u])
cnt+=f(v);
ct[u]=cnt;
return ct[u];
}``````
Here ct is the number of paths from u to 2.
dist is the distance from 2 to u.
Have i understood something wrong?

& i think Jan's 1st set of input is wrong because :
There is at most one path between any pair of intersections.

I have checked that there is no such input in which there is more than one pair of inputs between any pair of nodes.

Posted: Sat Feb 02, 2008 8:07 pm
Oh that was fully because of a small mistake in the implementation of dijkstra. Now got AC Jan's first set of output should be like this:

Code: Select all

``````6 9
1 6 2995
6 3 4827
3 1 32391
3 5 12382
5 4 18716
4 3 19895
6 1 1869
1 5 25667
5 2 17035``````
Ouput is the same as given by him.