Pagini recente » Cod sursa (job #210727) | Cod sursa (job #985233) | Cod sursa (job #712205) | Cod sursa (job #1920737) | Cod sursa (job #1283650)
#include <iostream>
#include <vector>
#include <fstream>
#include <cstring>
#include <algorithm>
using namespace std;
ifstream F("plan.in");
ofstream G("plan.out");
const int N = 265;
const int M = 1510;
/// ctcs
int n,m,mark[N],nbr;
vector<int> v[N],w[N],stack;
vector<int> ctc[N];
void go1(int x)
{
mark[x] = 1;
for (int i=0;i<int(v[x].size());++i)
{
int y = v[x][i];
if ( mark[y] == 0 )
go1( y );
}
stack.push_back(x);
}
void go2(int x)
{
mark[x] = 1;
ctc[nbr].push_back(x);
for (int i=0;i<int(w[x].size());++i)
{
int y = w[x][i];
if ( mark[y] == 0 )
go2( y );
}
}
void build_ctc()
{
for (int i=1;i<=n;++i)
if ( mark[i] == 0 )
go1(i);
memset(mark,0,sizeof(mark));
for (int i=int(stack.size())-1;i>=0;--i)
{
int x = stack[i];
if ( mark[x] == 0 )
{
++nbr;
go2(x);
}
}
memset(mark,0,sizeof(mark));
}
void print_ctc()
{
cerr<<nbr<<'\n';
for (int i=1;i<=nbr;++i,cerr<<'\n')
for (int j=0;j<int(ctc[i].size());++j)
cerr<<ctc[i][j]<<' ';
}
/// end of ctcs
int my_ctc[N],in[N],out[N],root[N];
vector< pair<int,int> > ctc_edges;
vector<int> sg[N];
vector<int> bg[N];
void build_sg()
{
for (int i=1;i<=nbr;++i)
for (int j=0;j<int(ctc[i].size());++j)
{
int x = ctc[i][j];
my_ctc[x] = i;
}
for (int i=1;i<=n;++i)
for (int j=0;j<int(v[i].size());++j)
{
int x = v[i][j];
if ( my_ctc[i] != my_ctc[x] )
ctc_edges.push_back( make_pair(my_ctc[i],my_ctc[x]) );
}
sort(ctc_edges.begin(),ctc_edges.end());
ctc_edges.erase( unique(ctc_edges.begin(),ctc_edges.end()) , ctc_edges.end());
for (int i=0;i<int(ctc_edges.size());++i)
{
int x = ctc_edges[i].first;
int y = ctc_edges[i].second;
out[x]++, in[y]++;
sg[x].push_back(y);
}
}
vector<int> leafs;
void find_leafs(int x)
{
mark[x] = 1;
for (int i=0;i<int(sg[x].size());++i)
{
int y = sg[x][i];
if ( mark[y] == 0 )
find_leafs(y);
}
if ( out[x] == 0 && in[x] != 0 ) // leaf
leafs.push_back(x);
}
void build_bg()
{
for (int i=1;i<=nbr;++i)
if ( in[i] == 0 && out[i] != 0 ) // root
{
memset(mark,0,sizeof(mark));
root[i] = 1;
vector<int>().swap(leafs);
find_leafs(i);
for (int j=0;j<int(leafs.size());++j)
bg[i].push_back( leafs[j] );
}
}
int pl[N],pr[N],co;
int pair_up(int x)
{
if ( pr[x] == 0 )
return 1;
int y = pr[x];
if ( mark[y] == 1 )
return 0;
mark[y] = 1;
for (int j=0;j<int(bg[y].size());++j)
if ( pair_up(bg[y][j]) )
{
pl[y] = bg[y][j];
pr[bg[y][j]] = y;
return 1;
}
return 0;
}
void cuple_edges()
// might be problem cause of all edges togeather
{
bool ok = 1;
while ( ok )
{
memset(mark,0,sizeof(mark));
ok = 0;
for (int i=1;i<=nbr;++i)
if ( pl[i] == 0 && root[i] )
for (int j=0;j<int(bg[i].size());++j)
if ( pair_up(bg[i][j]) )
{
pl[i] = bg[i][j];
pr[bg[i][j]] = i;
++co;
ok = 1;
break;
}
}
}
vector<int> other;
vector< pair<int,int> > matching,ans;
int main()
{
F>>n>>m;
for (int i=1,x,y;i<=m;++i)
{
F>>x>>y;
v[x].push_back(y);
w[y].push_back(x);
}
build_ctc();
// print_ctc();
build_sg();
build_bg();
cuple_edges();
memset(mark,0,sizeof(mark));
for (int i=1;i<=nbr;++i)
if ( pl[i] != 0 && mark[i] == 0 )
{
mark[i] = 1;
mark[pl[i]] = 1;
matching.push_back( make_pair( i , pl[i] ) );
}
for (int i=1;i<=nbr;++i)
if ( mark[i] == 0 )
other.push_back(i);
for (int i=0;i<int(matching.size())-1;++i)
ans.push_back( make_pair(matching[i].second , matching[i+1].first) );
if ( other.size() == 0 )
{
ans.push_back( make_pair(matching[int(matching.size())-1].second , matching[0].first) );
}
else
{
if ( ans.size() == 0 )
{
if ( other.size() > 1 ) // zgood
{
for (int i=0;i<int(other.size())-1;++i)
ans.push_back( make_pair(other[i],other[i+1]) );
ans.push_back( make_pair(other[int(other.size())-1] , other[0]) );
}
}
else
if ( other.size() != 0 ) // zgood
{
for (int i=0;i<int(other.size())-1;++i)
ans.push_back( make_pair(other[i],other[i+1]) );
ans.push_back( make_pair(matching[int(matching.size())-1].second , other[0]) );
ans.push_back( make_pair( other[int(other.size())-1] , matching[0].first ) );
}
}
G<<ans.size()<<'\n';
for (int i=0;i<int(ans.size());++i)
G<<ctc[ans[i].first][0]<<' '<<ctc[ans[i].second][0]<<'\n';
}