Pagini recente » Cod sursa (job #2775149) | Cod sursa (job #1476490) | Cod sursa (job #1353273) | Cod sursa (job #168120) | Cod sursa (job #2831857)
#include <bits/stdc++.h>
using namespace std;
ifstream fin( "dfs.in" );
ofstream fout( "dfs.out" );
int match[20005], dist[20005];
class graph {
private:
static const int INF = 2000'000'000;
int N; /// number of nodes
int t = 0; /// auxiliary variable, for different needs
vector< vector<int> > ad;
vector< vector<int> > reverseAd;
vector< vector<int> > cost;
vector<int> dist;
vector<int> low;
vector<int> parent;
vector<int> aux; /// auxiliary vector, for different needs
vector<pair<int,int> > criticalEdges;
int conexComponents; /// requires DFSTraversal to set the value
vector< vector<int> > adMat;
vector< vector<int> > flowMat;
vector< vector<int> > capMat;
void Dfs( int node ) {
aux.push_back( node );
dist[node] = 1;
for( int i = 0; i < ad[node].size(); ++i ) {
int w = ad[node][i];
if( dist[w] == 0 )
Dfs( w );
}
}
void Dfs2( int node, int parent, vector<vector<int> > &_solution ) {
dist[node] = low[node] = ++t;
aux.push_back( node );
for( int i = 0; i < ad[node].size(); ++i ) {
int w = ad[node][i];
if( w == parent ) continue;
if( dist[w] > 0 ) low[node] = min( low[node], dist[w] );
else {
Dfs2( w, node, _solution );
low[node] = min( low[node], low[w] );
if( low[w] >= dist[node] ) {
if( low[w] > dist[node] )
criticalEdges.push_back( { w, node } );
vector <int> tmp;
while( aux.back() != w ) {
tmp.push_back( aux.back() );
aux.pop_back();
}
tmp.push_back( aux.back() );
aux.pop_back();
tmp.push_back( node );
_solution.push_back( tmp );
}
}
}
}
void Dfs3( int node ) {
dist[node] = 1;
for( int i = 0; i < ad[node].size(); ++i ) {
int w = ad[node][i];
if( dist[w] == 0 )
Dfs3( w );
}
aux.push_back( node );
}
void Dfs4( int node, vector<int> &v ) {
dist[node] = 1;
v.push_back( node );
for( int i = 0; i < reverseAd[node].size(); ++i ) {
int w = reverseAd[node][i];
if( dist[w] == 0 )
Dfs4( w, v );
}
}
bool Dfs5( int nod ) {
if( nod == 0 ) return true;
int w;
for( int i = 0; i < ad[nod].size(); ++i ) {
w = ad[nod][i];
if( dist[ match[w] ] == dist[nod] + 1 && Dfs5( match[w] ) ) {
match[nod] = w;
match[w] = nod;
return true;
}
}
dist[nod] = INF;
return false;
}
bool isReachable() {
for( int i = 1; i <= N; ++i )
dist[i] = 0;
deque <int> Q;
dist[1] = 1;
Q.push_back( 1 );
int u, w;
while( !Q.empty() ) {
u = Q.front();
Q.pop_front();
if( u == N ) continue;
for( int i = 0; i < ad[u].size(); ++i ) {
w = ad[u][i];
if( !dist[w] && capMat[u][w] > flowMat[u][w] ) {
dist[w] = 1;
Q.push_back( w );
parent[w] = u;
}
}
}
return dist[N];
}
bool Bfs() {
deque <int> Q;
dist[0] = INF;
for( int i = 1; i <= N; ++i )
if( match[i] == 0 ) {
Q.push_back( i );
dist[i] = 0;
}
else dist[i] = INF;
int u, w;
while( !Q.empty() ) {
u = Q.front();
Q.pop_front();
if( u == 0 ) continue;
for( int i = 0; i < ad[u].size(); ++i ) {
w = ad[u][i];
if( dist[ match[w] ] == INF ) {
dist[ match[w] ] = dist[u] + 1;
Q.push_back( match[w] );
}
}
}
return ( dist[0] < INF );
}
public:
graph( int n ) {
N = n;
ad.resize( n + 1 );
//cost.resize( n + 1 );
dist.resize( n + 1 );
//low.resize( n + 1 );
//reverseAd.resize( n + 1 );
//parent.resize( n + 1 );
//vector <int> tmp(n + 1);
//for( int i = 0; i <= n; i++ ) {
// adMat.push_back( tmp );
// flowMat.push_back( tmp );
// capMat.push_back( tmp );
//}
}
void changeN( int n ) {
N = n;
ad.resize( n + 1 );
cost.resize( n + 1 );
//dist.resize( n + 1 );
low.resize( n + 1 );
reverseAd.resize( n + 1 );
parent.resize( n + 1 );
vector <int> tmp(n + 1);
for( int i = 0; i <= n; i++ ) {
adMat.push_back( tmp );
flowMat.push_back( tmp );
capMat.push_back( tmp );
}
}
int getN() { return N; }
void addEdge( int x, int y, bool directed = false, int c = 0 ) {
ad[x].push_back(y);
//cost[x].push_back(c);
//reverseAd[y].push_back(x);
if( !directed ) {
ad[y].push_back(x);
//cost[y].push_back(c);
//reverseAd[x].push_back(y);
}
//adMat[x][y] = c;
//if( !directed ) adMat[y][x] = c;
}
void addFlowEdge( int x, int y, int cap ) {
capMat[x][y] = capMat[y][x] = cap;
}
void setAdMat( vector<vector<int> > mat ) {
adMat = mat;
}
vector <int> dfsTraversal() {
aux.clear();
conexComponents = 0;
for( int i = 1; i <= N; ++i )
dist[i] = 0;
for( int i = 1; i <= N; i++ )
if( dist[i] == 0 ) {
Dfs( i );
++conexComponents;
}
return aux;
}
void bfsTraversal( int source ) {
queue<int> Q;
for( int i = 0; i <= N; i++ )
dist[i] = 0;
dist[source] = 1;
Q.push( source );
while( !Q.empty() ) {
int u = Q.front();
Q.pop();
for( int i = 0; i < ad[u].size(); ++i ) {
int w = ad[u][i];
if( dist[w] == 0 ) {
dist[w] = dist[u] + 1;
Q.push( w );
}
}
}
}
int graphDiameter() {
bfsTraversal( 1 );
int maxDist = -1, maxNode;
for( int i = 1; i <= N; ++i )
if( dist[i] > maxDist ) {
maxDist = dist[i];
maxNode = i;
}
bfsTraversal( maxNode );
maxDist = -1;
for( int i = 1; i <= N; ++i )
maxDist = max( maxDist, dist[i] );
return maxDist;
}
vector<int>getTopologicalSort() {
aux.clear();
for( int i = 1; i <= N; i++ )
dist[i] = 0;
for( int i = 1; i <= N; i++ )
if( dist[i] == 0 )
Dfs3( i );
return aux;
}
vector<vector<int> > getStronglyConnectedComponents() {
vector<vector<int> > sol;
vector<int> topologicalSort = getTopologicalSort();
for( int i = 0; i <= N; i++ )
dist[i] = 0;
for( int i = topologicalSort.size() - 1; i >= 0; --i ) {
int node = topologicalSort[i];
if( dist[node] ) continue;
vector<int> tmp;
Dfs4( node, tmp );
sol.push_back( tmp );
}
return sol;
}
vector<vector<int> > getBiconnectedComponents() {
vector<vector<int> > sol;
for( int i = 1; i <= N; ++i )
if( dist[i] == 0 )
Dfs2( i, 0, sol );
return sol;
}
int getConexComponents() { /// requires DFS to be called first
return conexComponents;
}
//vector <int> getDistances() { /// requires BFS to be called first
// return dist;
//}
vector <pair<int,int> > getCriticalEdges() { /// requires getBiconnectedComps to be called first
return criticalEdges;
}
int maxFlow() {
int totFlow = 0;
int currentFlow;
while( isReachable() ) {
for( int i = 0; i < ad[N].size(); ++i ) {
int aux = ad[N][i];
if( capMat[aux][N] == flowMat[aux][N] || !dist[aux] ) continue;
currentFlow = INF;
parent[N] = aux;
for( int i = N; i != 1; i = parent[i] )
currentFlow = min( currentFlow, capMat[ parent[i] ][i] - flowMat[ parent[i]][i] );
for( int i = N; i != 1; i = parent[i] ) {
flowMat[ parent[i] ][i] += currentFlow;
flowMat[i][ parent[i] ] -= currentFlow;
}
totFlow += currentFlow;
}
}
return totFlow;
}
static bool HavelHakimiUtillity( vector<int> degree ) {
while( !degree.empty() ) {
sort( degree.begin(), degree.end() );
if( degree.back() < 0 )
return false;
if( degree.back() > degree.size() - 1 )
return false;
for( int i = 1; i <= degree.back(); ++i )
degree[degree.size() - i - 1]--;
degree.pop_back();
}
return true;
}
vector <vector<int> > royFloyd() {
vector< vector<int> > dist;
for( int i = 0; i <= N; ++i ) {
vector<int> tmp;
tmp.resize( N + 1 );
dist.push_back( tmp );
}
for( int i = 1; i <= N; ++i )
for( int j = 1; j <= N; ++j )
dist[i][j] = INF;
for( int i = 1; i <= N; ++i )
for( int j = 1; j <= N; ++j )
if( adMat[i][j] ) dist[i][j] = adMat[i][j];
for( int k = 1; k <= N; ++k )
for( int i = 1; i <= N; ++i )
for( int j = 1; j <= N; ++j )
if( i != j )
if( dist[i][k] < INF && dist[k][j] < INF && dist[i][j] > dist[i][k] + dist[k][j] )
dist[i][j] = dist[i][k] + dist[k][j];
return dist;
}
bool isEulerian() {
for( int i = 0; i < ad.size(); ++i )
if( ad[i].size() % 2 )
return false;
return true;
}
vector <int> eulerCycle() {
vector<int> ans;
int w, nod;
bool found;
deque <int> S;
S.push_back( 1 );
while( !S.empty() ) {
nod = S.back();
S.pop_back();
found = false;
while( !ad[nod].empty() && !found ) {
w = ad[nod].back();
ad[nod].pop_back();
if( w == -1 ) continue;
S.push_back( nod );
S.push_back( w );
for( int i = 0; i < ad[w].size(); ++i )
if( ad[w][i] == nod ) {
ad[w][i] = -1;
break;
}
found = true;
}
if( found ) continue;
else ans.push_back( nod );
}
return ans;
}
int maximalMatching() {
int matching = 0;
while( Bfs() )
for( int i = 1; i <= N; ++i )
if( match[i] == 0 && Dfs5( i ) )
++matching;
return matching;
}
};
int main()
{
int n, m;
fin >> n >> m;
graph G(n);
int x, y;
for( int i = 1; i <= m; i++ ) {
fin >> x >> y;
G.addEdge( x, y, false );
}
vector <int> X = G.dfsTraversal();
//for( int i = 0; i < X.size(); ++i )
// fout << X[i] << ' ';
fout << G.getConexComponents();
return 0;
}