I get cygwin_exception::open_stackdumpfile trying to run my code. I guess it is an error concerning memory. I am almost 100% sure I get this error because of not properly creating, sending to function or dealing with maximalSets and/or compsub vectors.
Please help me to solve this error and thank you for all your answers!
update: fixed the problem pointed out by Paul Evans. Now I get the exception from time to time, but still get it.
class Graph {
private:
int size; // the number of node
vector<vector<bool> > connected;
vector<vector<int> > bkv2(vector<int> oldSet, int ne, int ce,
vector<int> &compsub, vector<vector<int> > maximalSets);
public:
Graph(int size);
vector<vector<int> > findMaximalSets();
}
Graph::Graph(int n) {
int i, j;
srand((unsigned int) time( NULL));
size = n;
connected.resize(size);
for (int i=0; i<size; i++) {
connected[i].resize(size);
}
for (i = 0; i < size; i++) { // the graph is randomly generated
connected[i][i] = 1;
for (j = i + 1; j < size; j++) {
if (rand() % 2 == 1) {
connected[i][j] = 1;
connected[j][i] = 1;
} else {
connected[i][j] = 0;
connected[j][i] = 0;
}
}
}
}
vector<vector<int> > Graph::findMaximalSets() {
int i;
vector<int> all(size);
vector<int> compsub;
vector<vector<int> > maximalSets;
for (i = 0; i < size; i++) {
all[i] = i;
}
return bkv2(all, 0, size, compsub, maximalSets);
}
vector<vector<int> > Graph::bkv2(vector<int> oldSet, int ne, int ce,
vector<int> &compsub, vector<vector<int> > maximalSets) {
vector<int> newSet(ce);
int nod, fixp;
int newne, newce, i, j, count, pos, p, s, sel, minnod;
minnod = ce;
nod = 0;
for (i = 0; i < ce && minnod != 0; i++) {
p = oldSet[i];
count = 0;
for (j = ne; j < ce && count < minnod; j++)
if (connected[p][oldSet[j]]) {
count++;
pos = j;
}
if (count < minnod) {
fixp = p;
minnod = count;
if (i < ne) {
s = pos;
} else {
s = i;
nod = 1;
}
}
}
for (nod = minnod + nod; nod >= 1; nod--) {
p = oldSet[s];
oldSet[s] = oldSet[ne];
sel = oldSet[ne] = p;
newne = 0;
for (i = 0; i < ne; i++) {
if (!connected[sel][oldSet[i]]) {
newSet[newne++] = oldSet[i];
}
}
newce = newne;
for (i = ne + 1; i < ce; i++) {
if (!connected[sel][oldSet[i]]) {
newSet[newce++] = oldSet[i];
}
}
compsub.push_back(sel);
if (newce == 0) {
vector<int> copy = compsub;
maximalSets.push_back(copy);
} else if (newne < newce) {
maximalSets = bkv2(newSet, newne, newce, compsub, maximalSets);
}
compsub.pop_back();
ne++;
if (nod > 1) {
for (s = ne; !connected[fixp][oldSet[s]]; s++) {
}
}
}
return maximalSets;
}
It's because you're not initializing size anywhere.
Related
I'm getting an error message in Codeblocks C++ 'Program received signal SIGSEGV, Segmentation fault' in comparison between a vector element and a size of vector of vectors inside for loop (line 133 if (parz_przestrzenie[i] != parz_dystanse[i].size())).
Could anyone tell me why?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int bloki_parz[100000], bloki_nieparz[100000];
int silnia(int n)
{
int liczba = 1;
for (int i = 1; i <= n; i++)
{
liczba *= i;
}
return liczba;
}
int main()
{
int n, czapka, wolne_miejsca = 0, wynik = 1;
vector<int> parz, nieparz, parz_przestrzenie, nieparz_przestrzenie, parz_przestrzenie2, nieparz_przestrzenie2;
vector<vector<int>> parz_dystanse;
vector<vector<int>> nieparz_dystanse;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> czapka;
if (i % 2 == 0)
{
parz.push_back(czapka);
}
else
{
nieparz.push_back(czapka);
}
}
int parz_size = parz.size(), nieparz_size = nieparz.size();
// sprawdzamy czy dane nie sÂą sprzeczne ; gdy zabraknie nam miejsc do rozmieszczania
vector<int> parz_duplicate = parz;
vector<int> nieparz_duplicate = nieparz;
parz_duplicate.erase(unique(parz_duplicate.begin(), parz_duplicate.end()), parz_duplicate.end());
nieparz_duplicate.erase(unique(nieparz_duplicate.begin(), nieparz_duplicate.end()), nieparz_duplicate.end());
int parz_dupl_size = parz_duplicate.size(), nieparz_dupl_size = nieparz_duplicate.size();
if (parz_size < nieparz_dupl_size)
{
cout << 0 << endl;
return 0;
}
if (nieparz_size < parz_dupl_size)
{
cout << 0 << endl;
return 0;
}
for (int i = 0; i < parz_size - 1; i++)
{
if (parz[i] == parz[i + 1])
{
bloki_parz[i + 1] = 1;
}
}
for (int i = 0; i < nieparz_size - 1; i++)
{
if (nieparz[i] == nieparz[i + 1])
{
bloki_nieparz[i] = 1;
}
}
for (int i = 0; i < parz_size; i++)
{
vector<int> bloczek;
for (int j = i; j < parz_size; j++)
{
if (parz[j] != parz[j + 1])
{
bloczek.push_back(parz[j]);
}
else
{
i += 1;
break;
}
}
if (bloczek.size() != 0)
{
parz_dystanse.push_back(bloczek);
}
}
int parz_dyst_size = parz_dystanse.size();
if (parz[parz_size - 1] != parz[parz_size - 2])
{
parz_dystanse[parz_dyst_size - 1].push_back(parz[parz_size - 1]);
}
for (int i = 0; i < nieparz_size; i++)
{
vector<int> bloczek;
for (int j = i; j < nieparz_size; j++)
{
if (nieparz[j] != nieparz[j + 1])
{
bloczek.push_back(nieparz[j]);
}
else
{
i += 1;
break;
}
}
if (bloczek.size() != 0)
{
nieparz_dystanse.push_back(bloczek);
}
}
int nieparz_dyst_size = nieparz_dystanse.size();
int current_wynik = 0;
for (int i = 0; i < nieparz_size; i++)
{
if (bloki_parz[i] == 0)
{
current_wynik++;
}
else
{
if (current_wynik != 0)
{
parz_przestrzenie.push_back(current_wynik);
}
current_wynik = 0;
}
}
parz_przestrzenie.push_back(current_wynik);
current_wynik = 0;
for (int i = 0; i < parz_size; i++)
{
if (bloki_nieparz[i] == 0)
{
current_wynik++;
}
else
{
if (current_wynik != 0)
{
nieparz_przestrzenie.push_back(current_wynik);
}
current_wynik = 0;
}
}
nieparz_przestrzenie.push_back(current_wynik);
int parz_przest_size = parz_przestrzenie.size(), nieparz_przest_size = nieparz_przestrzenie.size();
for (int i = 0; i < 1; i++)
{
if (parz_przestrzenie[i] != parz_dystanse[i].size())
{
wynik *= parz_przestrzenie[i];
wolne_miejsca++;
}
}
for (int i = 0; i < nieparz_przest_size; i++)
{
if (nieparz_przestrzenie[i] != nieparz_dystanse[i].size())
{
wynik *= nieparz_przestrzenie[i];
wolne_miejsca++;
}
}
cout << wynik * silnia(wolne_miejsca) << endl;
}
parz_dystanse is a vector of a vector. In this case the return value of parz_dystanse.size() is a long unsigned int, whereas an element of parz_przestrzenie is an int.
You need to make explicit that parz_dystanse.size() returns an int in order to make comparitions between integer expressions of different signedness.
This will fix that problem:
if (parz_przestrzenie[i] != (int)parz_dystanse[i].size())
I am trying to solve shortest path for big graph using dijkstra algorithm.
Problem is when I am executing program in CLion I am getting std::bad alloc, always at node 491, however when I tried do the same on my Ubuntu VM, I am getting core dumped on the beggining.
I am new to c++ so it is hard for me to understand why does it happen.
Here is my code:
Utils:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <ctime>
#define INFINITY 9999999
int maxNode = 0;
using namespace std;
vector<int> loadFile(const string &path) {
vector<int> graph;
ifstream file;
file.open(path);
if (!file.fail()) {
string line;
while (getline(file, line)) {
stringstream ss(line);
for (int i; ss >> i;) {
if (i + 1 > maxNode)
maxNode = i + 1;
graph.push_back(i);
if (ss.peek() == ';')
ss.ignore();
}
}
file.close();
}
return graph;
}
int **formatGraph(vector<int> inData) {
int **graph = 0;
int currentIndex = 0;
int srcNode = inData[0];
int dstNode = inData[1];
int cost = inData[2];
graph = new int *[maxNode];
for (int i = 0; i < maxNode; i++) {
graph[i] = new int[maxNode];
for (int j = 0; j < maxNode; j++) {
if (srcNode == i && dstNode == j) {
graph[i][j] = cost;
currentIndex++;
srcNode = inData[currentIndex * 3];
dstNode = inData[currentIndex * 3 + 1];
cost = inData[currentIndex * 3 + 2];
//printf("%d %d\n", i, j);
} else
graph[i][j] = 0;
}
}
for (int i = 0; i < maxNode; i++) {
for (int j = 0; j < maxNode; j++) {
graph[j][i] = graph[i][j];
}
}
return graph;
}
Algorithm:
void dijkstra(int **G, int n, int startnode) {
printf("%d\n", startnode);
int **cost = new int *[maxNode];
int distance[maxNode], pred[maxNode];
int visited[maxNode], count, mindistance, nextnode, i, j;
for (i = 0; i < n; i++) {
cost[i] = new int[maxNode];
for (j = 0; j < n; j++)
cost[i][j] = 0;
}
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (G[i][j] == 0)
cost[i][j] = INFINITY;
else
cost[i][j] = G[i][j];
for (i = 0; i < n; i++) {
distance[i] = cost[startnode][i];
pred[i] = startnode;
visited[i] = 0;
}
distance[startnode] = 0;
visited[startnode] = 1;
count = 1;
while (count < n - 1) {
mindistance = INFINITY;
for (i = 0; i < n; i++) {
if (distance[i] < mindistance && !visited[i]) {
mindistance = distance[i];
nextnode = i;
}
}
visited[nextnode] = 1;
for (i = 0; i < n; i++) {
if (!visited[i]) {
if (mindistance + cost[nextnode][i] < distance[i]) {
distance[i] = mindistance + cost[nextnode][i];
pred[i] = nextnode;
}
}
}
count++;
}
delete[] cost;
for (i = 0; i < n; i++)
if (i != startnode) {
j = i;
do {
j = pred[j];
} while (j != startnode);
}
}
And here is my main function:
int main() {
vector<int> graph = loadFile("..\\data\\newFile2.csv");
int **graphConverted = formatGraph(graph);
//printMatrix(graphConverted);
clock_t begin = clock();
for (int i = 0; i < maxNode; i++)
dijkstra(graphConverted, maxNode, i);
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
printf("\nTime: %f", elapsed_secs);
return 0;
}
First the data is loaded into vector, and then it is converted to adjacency matrix.
Data is stored in form:
src_node;dst_node;cost
1;2;3
1;3;30
1;66;20
etc.
Dataset consinsts of 1004 nodes and 25571 edges.
Could you please suggest me any solution how to fix this?
In dijkstra you have dynamic memory allocations here:
int **cost = new int *[maxNode];
and here in a loop over i:
cost[i] = new int[maxNode];
You have only one call to delete[] in this function:
delete[] cost;
So all the allocations from the second new line are guaranteed to be leaked. After a while you will be out-of-memory, resulting in the std::bad_alloc.
You need to match each new[] call with exactly one delete[] call.
Don't use new/delete at all. Instead declare all your arrays as std::vector, which will take care of this automatically.
Also don't use variable-length arrays such as
int distance[maxNode], pred[maxNode];
They are a non-standard compiler extension. Make these std::vector as well.
I am currently trying to implement generalized suffix array according to the algorithm described in this paper: paper.
However I am stuck at the moment with implementation of the sorting algorithm in chapter 2.
My current c++ code looks roughly like this (my alphabet is lowercase English letters):
std::vector<std::pair<int,int>> suffix_array(const std::vector<std::string>& ss) {
std::vector<std::vector<std::pair<int,int>>> tmp(26);
size_t n = 0;
for (size_t i = 0; i < ss.size(); i++) {
if (ss[i].length() > n) {
n = ss[i].length();
}
for (size_t j = 0; j < ss[i].length(); j++) {
tmp[ss[i][j] - 'a'].push_back(std::make_pair(i,j));
}
}
// initialize pos
std::vector<std::pair<int,int>> pos;
std::vector<bool> bh;
for (auto &v1 : tmp) {
bool b = true;
for (auto &p: v1) {
pos.push_back(p);
bh.push_back(b);
b = false;
}
}
// initialze inv_pos
std::map<std::pair<int,int>,int> inv_pos;
for (size_t i = 0; i < pos.size(); i++) {
inv_pos[pos[i]] = i;
}
int H = 1;
while (H <= n) {
std::vector<int> count(pos.size(), 0);
std::vector<bool> b2h(bh);
for (size_t i = 0, j = 0; i < pos.size(); i++) {
if (bh[i]) {
j = i;
}
inv_pos[pos[i]] = j;
}
int k = 0;
int i = 0;
while (i < pos.size()) {
int j = k;
i = j;
do {
auto t = std::make_pair(pos[i].first, pos[i].second - H);
if (t.second >= 0) {
int q = inv_pos[t];
count[q] += 1;
inv_pos[t] += (count[q] - 1);
b2h[inv_pos[t]] = true;
}
i++;
} while (i < pos.size() && !bh[i]);
k = i;
i = j;
do {
auto t = std::make_pair(pos[i].first, pos[i].second - H);
if (t.second >= 0) {
int q = inv_pos[t];
if ((j <= q) && (q < k) && (j <= (q+1)) &&
((q+1) < k) && b2h[q+1]) {
b2h[q+1] = false;
}
}
i++;
} while (i < k);
}
bh = b2h;
for (auto &x : inv_pos) {
pos[x.second] = x.first;
}
H *= 2;
}
return pos;
}
At the moment, I get garbage results with my implementation. And I don't quite understand from the algorithm description in the paper how inv_pos is correctly updated after each stage...
If someone can spot what is wrong with my implementation and show me the right direction with brief explanation, I would be really grateful.
I have a constraint set for each vehicle "p" and each arc (k,m) that belongs to this vehicle route.
At each iteration, I change the route of a vehicle.
Then, at each iteration, I need to change the constraints related to this vehicle. For a specific "p", I need to delete the constraints related to it and add new ones.
How can I do this?
I don't know how to use the remove function in this case. How can I identify the subset constraints related to "p" to be deleted? In the way I'm doing I'm deleting the always the first constraints of the set.
typedef struct{
IloCplex cplex;
IloEnv env;
IloModel mod;
IloNumVarArray f;
IloNumArray _f;
IloNumVarArray q;
IloNumArray _q;
IloRangeArray constraints_r3;
IloObjective fo;
IloNum _fo;
} CPX_RHLPflow;
struct DATA {
int n;
vector<vector<vector<int> > > _x;
int p;
vector<double> tau;
};
int MAPf (int router, int nodei, int nodej, int nodeu, int nodev, int N) {
return router*N*N*N*N+nodei*N*N*N+nodej*N*N+nodeu*N+nodev;
}
void create_model_RHLPflow(CPX_RHLPflow &mono, DATA data){
IloEnv& env = mono.env;
mono.mod = IloModel(env);
mono.cplex = IloCplex(mono.mod);
int sizef = data.p*data.n*data.n*data.n*data.n;
mono.f = IloNumVarArray(env, sizef, 0.0, +IloInfinity, ILOFLOAT);
mono._f = IloNumArray(env,sizef);
mono.q = IloNumVarArray(env, data.p, 0.0, +IloInfinity, ILOFLOAT);
mono._q = IloNumArray(env,data.p);
mono.constraints_r3 = IloRangeArray(env);
char name[50];
for (int p = 0; p < data.p; p++) {
for (int k = 0; k < data.n; k++) {
for (int m = 0; m < data.n; m++) {
if (k != m) {
if (data._x[p][k][m] == 1) {
IloExpr r_3(env);
for (int i = 0; i < data.n; i++) {
for (int j = 0; j < data.n; j++) {
if (i != j) {
if (k != j and m != i) {
r_3 += mono.f[MAPf(p,i,j,k,m,data.n)] ;
sprintf(name, "f(%d,%d,%d,%d,%d)",p,i,j,k,m);
mono.f[MAPf(p,i,j,k,m,data.n)].setName(name);
}
}
}
}
r_3 -= mono.q[p] * data.tau[p];
sprintf(name, "q(%d)",p);
mono.q[p].setName(name);
IloRange ctr;
ctr = (r_3 <= 0);
sprintf(name, "r3_%d_%d_%d",p,k,m);
ctr.setName(name);
mono.constraints_r3.add(ctr);
r_3.end();
}
}
}
}
}
mono.mod.add(mono.constraints_r3);
}
void DeleteConstraints (CPX_RHLPflow &mono, DATA data, int vehicle) {
char name[50];
int cont = 0;
for (int p = 0; p < data.p; p++) {
if (vehicle == p) {
for (int k = 0; k < data.n; k++) {
for (int m = 0; m < data.n; m++) {
if (k != m) {
if (data._x[p][k][m] == 1) {
mono.mod.remove(mono.constraints_r3[cont]);
cont += 1;
}
}
}
}
break;
}
}
sprintf(name, "ModelAfterModification.lp");
mono.cplex.exportModel(name);
}
int main(int argc, char* argv[]) {
CPX_RHLPflow mono;
DATA data;
data.n = 5;
data.p = 3;
data._x = vector<vector<vector<int> > > (data.p, vector<vector<int> > (data.n, vector<int> (data.n,0)));
data.tau = vector<double> (data.p, 1.00);
data._x[0][0][1] = 1;
data._x[0][1][3] = 1;
data._x[0][3][4] = 1;
data._x[0][4][0] = 1;
data._x[1][2][4] = 1;
data._x[1][4][3] = 1;
data._x[1][3][2] = 1;
data._x[2][1][2] = 1;
data._x[2][2][3] = 1;
data._x[2][3][4] = 1;
data._x[2][4][1] = 1;
cout << "oi" << endl;
create_model_RHLPflow (mono, data);
char name[50];
sprintf(name, "ModelBeforeModification.lp");
mono.cplex.exportModel(name);
int vehicle = 1;
DeleteConstraints(mono,data,vehicle);
data._x[1][2][4] = 0;
data._x[1][4][3] = 0;
data._x[1][3][2] = 0;
data._x[1][2][3] = 1;
data._x[1][3][1] = 1;
data._x[1][1][4] = 1;
data._x[1][4][2] = 1;
return 0;
}
If I right understood your question, you can use the solution below.
// Insert the constraint
// bc <- my branch-and-cut class
// bc.env_ <- IloEnv
// expr <- IloExpr
// x <- integer
IloRange neigboor(bc.env_, -IloInfinity, expr, x, "constraintName");
// model_ <- IloModel
bc.model_->add(neigboor);
bc.solve();
bc.model_->remove(neigboor);
neigboor.end();
You can repeat it indefinitely, adding or removing as many constraints as you want.
I used the above code to perform local searches using CPLEX as neighborhood solver.
I am trying to solve http://www.spoj.com/problems/BOTTOM/
Here are the steps I am following:
1) Find the strongly connected components using Kosaraju's algorithm. 2) Consider a strongly connected component. Consider an edge u. Now consider all edges from u to some vertice v. If v lies in some other SCC, eliminate the whole strongly conected component. Else include all the elements in the solution.
However, I am constantly getting WA. Please help.
Here is my code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <fstream>
#include <iterator>
#include <queue>
using namespace std;
int k = 0;
int V, E;
bool fix[5001];
bool fix2[5001];
int compNum[5001];
void dfs(int v, vector< vector<int> >&G, bool *fix, vector <int> &out) {
fix[v] = true;
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i];
if (!fix[u]) {
fix[u] = true;
dfs(u, G, fix, out);
}
}
out.push_back(v);
}
void dfs2(int v, vector< vector<int> >&G, bool *fix2, vector < vector<int> > &components) {
fix2[v] = true;
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i];
if (!fix2[u]) {
fix2[u] = true;
dfs2(u, G, fix2, components);
}
}
components[k].push_back(v);
compNum[v] = k;
}
int main() {
int a, b;
while (true) {
cin >> V; if (V == 0) break; cin >> E;
vector< vector<int> >G(V + 1);
vector< vector<int> >G2(V + 1);
vector<int>out;
vector < vector<int> >components(V + 1);
for (int i = 0; i < E; i++) {
cin >> a >> b;
G[a].push_back(b);
G2[b].push_back(a);
}
for (int i = 1; i <= V; i++) {
if (!fix[i])
dfs(i, G, fix, out);
}
reverse(out.begin(), out.end());
for (int i = 0; i < out.size(); i++){
if (!fix2[out[i]]) {
dfs2(out[i], G2, fix2, components);
k++;
}
}
vector<int>gamotana;
for (int i = 0; i < components.size(); i++) {
for (int j = 0; j < components[i].size(); j++) {
bool check = true;
for (int z = 0; z < G[components[i][j]].size(); z++)
{
if (compNum[G[components[i][j]][z]] != i)
{
check = false; goto next123;
}
}
if (check)
gamotana.push_back(components[i][j]);
}
next123:;
}
sort(gamotana.begin(), gamotana.end());
for (int i = 0; i < gamotana.size(); i++)
cout << gamotana[i] << " ";
for (int i = 0; i < 5001; i++) {
fix[i] = false;
fix2[i] = false;
compNum[i] = -1;
}
k = 0;
cout << endl;
}
return 0;
}
In your algorithm description you say you eliminate the entire connected component if some edge leads to a different component.
However, in your code you appear to add all vertices j in component i to your solution until you find an edge leading out. In other words, even if a component is not a sink you may still incorrectly report some of the vertices as being sinks.
I imagine you should do something more like this:
for (int i = 0; i < components.size(); i++) {
for (int j = 0; j < components[i].size(); j++) {
for (int z = 0; z < G[components[i][j]].size(); z++)
{
if (compNum[G[components[i][j]][z]] != i)
{
goto next123;
}
}
}
for (int j = 0; j < components[i].size(); j++)
gamotana.push_back(components[i][j]);
next123:;
}
Of course, there may be more issues. I would recommend you try constructing and testing some small examples first, and perhaps testing against a brute force solver to identify failing cases.
#include<bits/stdc++.h>
using namespace std;
void dfs(vector<int>* edges, stack<int>& finishedVertices, bool* visited, int n, int start){
visited[start] = true;
for(int i = 0 ; i < edges[start].size() ; i++){
int node = edges[start][i];
if(!visited[node]){
dfs(edges, finishedVertices, visited, n, node);
}
}
finishedVertices.push(start);
}
void dfs_reverse(vector<int>* edgesT, bool* visited, unordered_map<int,vector<int>>& SCC, int node, int k){
SCC[k].push_back(node);
visited[node] = true;
for(int i = 0 ; i < edgesT[node].size() ; i++){
int new_node = edgesT[node][i];
if(!visited[new_node]){
dfs_reverse(edgesT, visited, SCC, new_node, k);
}
}
}
void getSCC(vector<int>* edges, vector<int>* edgesT, int n){
bool* visited = new bool[n];
for(int i = 0 ; i < n ; i++){
visited[i] = false;
}
stack<int> finishedVertices;
for(int i = 0 ; i < n ; i++){
if(!visited[i]){
dfs(edges, finishedVertices, visited, n, i);
}
}
unordered_map<int,vector<int>> SCC;
int k = 0;
for(int i = 0 ; i < n ; i++){
visited[i] = false;
}
while(!finishedVertices.empty()){
int node = finishedVertices.top();
finishedVertices.pop();
if(!visited[node]){
dfs_reverse(edgesT, visited, SCC, node, k);
k++;
}
}
int flag = 1;
vector<int> ans;
vector<int> bottom;
for(int i = 0 ; i < k ; i++){
for(int j = 0 ; j < SCC[i].size(); j++){
ans.push_back(SCC[i][j]);
}
for(int m = 0 ; m < ans.size() ; m++){
int node = ans[m];
for(int j = 0 ; j < edges[node].size() ; j++){
int new_node = edges[node][j];
vector<int> :: iterator it;
it = find(ans.begin(), ans.end(), new_node);
if(it == ans.end()){
flag = 0;
break;
}
}
if(flag == 0)
break;
}
if(flag == 1){
for(int j = 0 ; j < ans.size() ; j++)
bottom.push_back(ans[j]);
}
flag = 1;
ans.clear();
}
sort(bottom.begin(), bottom.end());
for(int i = 0 ; i < bottom.size() ; i++)
cout << bottom[i] + 1 << " ";
cout << endl;
}
int main(){
while(true){
int n;
cin >> n;
if(n == 0)
break;
vector<int>* edges = new vector<int>[n];
vector<int>* edgesT = new vector<int>[n];
int e;
cin >> e;
for(int i = 0 ; i < e ; i++){
int x, y;
cin >> x >> y;
edges[x-1].push_back(y-1);
edgesT[y-1].push_back(x-1);
}
getSCC(edges, edgesT, n);
delete [] edges;
delete [] edgesT;
}
return 0;
}