Pagini recente » Cod sursa (job #1688994) | Cod sursa (job #2116603) | Cod sursa (job #2300478) | Cod sursa (job #3280787) | Cod sursa (job #1024087)
#include <fstream>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
ifstream F("nowhere-zero.in");
ofstream G("nowhere-zero.out");
/**
Construiesc regiunile si trag muchie intre pentru laturile comune din regiuni diferite.
Muchiile initiale le orientez. Intai fac un vector next care as ma trimita la urmatorul
punct. Cand ajung in acelasi punct am epuziat o regiune.
Colorez graful regiunilor si apoi contruiesc reteaua de circulatie. Colorarea se face cu
6 culori , deci pornesc de la graf minim si elimin din graf.
Complexitatea: O(N log N)
*/
const int Nmax = 100010;
#define IT(type) vector<type>::iterator
#define parc(type,it,vect) for (vector< type >::iterator it=vect.begin();it!=vect.end();++it)
#define x first
#define y second
int N,M,K;
pair<double,double> point[Nmax];
pair<int,int> edges[Nmax<<1];
vector<int> V[Nmax];
vector< vector<int> > regions;
int r_index[Nmax<<1];
vector< vector<int> > graph;
int next[Nmax<<1];
double angle[Nmax<<1];
void read_data()
{
F>>N>>M;
for (int i=1;i<=N;++i)
F>>point[i].x>>point[i].y;
for (int i=1,x,y;i<=M;++i)
{
F>>x>>y;
edges[i] = make_pair(x,y);
edges[i+M] = make_pair(y,x);
V[x].push_back( i );
V[y].push_back( i+M );
}
}
bool angle_cmp(int x,int y)
{
return angle[x] < angle[y];
}
int reverse_index(int x)
{
if ( x > M )
return x-M;
return x+M;
}
void compute_next()
{
for (int i=1;i<=N;++i)
{
parc(int,e,V[i])
angle[*e] = atan2(point[edges[*e].y].y-point[i].y,point[edges[*e].y].x-point[i].x);
sort(V[i].begin(),V[i].end(),angle_cmp);
for (size_t j=0;j<V[i].size();++j)
next[reverse_index(V[i][j])] = V[i][(i+1)%(int(V[i].size()))];
}
}
bool used[Nmax<<1];
void build_regions()
{
for (int x=1;x<=N;++x)
parc(int,nowe,V[x])
if ( used[*nowe] == 0 )
{
int e = *nowe;
vector<int> region;
for (;used[e] != 0 && edges[e].y != x ; e = next[e])
{
region.push_back(e);
r_index[e] = int(regions.size());
used[e] = 1;
}
if ( !used[e] )
{
region.push_back(e);
r_index[e] = int(regions.size());
used[e] = 1;
}
if ( region.size() )
regions.push_back( region );
}
K = regions.size();
}
void place_edges()
{
graph.resize(K+5);
for (int i=1;i<=M*2;++i)
{
graph[ r_index[i] ].push_back( r_index[reverse_index(i)] );
graph[ r_index[reverse_index(i)] ].push_back( r_index[i] );
}
for (int i=0;i<K;++i)
{
sort(graph[i].begin(),graph[i].end());
graph[i].erase( unique(graph[i].begin(),graph[i].end()) , graph[i].end() );
}
}
const int Colors = 6;
vector<int> degree;
vector<int> order;
vector<int> color;
queue<int> q;
vector<int> mark;
int get_color(int node)
{
int X[Colors+5];
parc(int,it,graph[node])
X[color[*it]] = 1;
int now = 1;
while ( X[now] == 1 )
++now;
return now;
}
void color_graph()
{
degree.resize(K+5);
mark.resize(K+5);
color.resize(K+5);
for (int i=0;i<K;++i)
degree[i] = int(graph[i].size());
for (int i=0;i<K;++i)
if ( degree[i] == Colors )
{
mark[i] = 1;
q.push( i );
}
while ( q.size() )
{
int now = q.front();
order.push_back( now );
q.pop();
parc(int,it,graph[now])
if ( --degree[*it] <= Colors && mark[*it] == 0 )
{
mark[*it] = 1;
q.push(*it);
}
}
for (int i=int(order.size())-1;i>=0;--i)
color[ order[i] ] = get_color(i);
}
void print_data()
{
for (int i=1;i<=(M<<1);++i)
{
int flow = color[ r_index[i] ] - color[ r_index[reverse_index(i)] ];
if ( flow < 0 ) continue;
G<<edges[i].x<<' '<<edges[i].y<<' '<<flow<<'\n';
}
}
int main()
{
read_data();
compute_next();
build_regions();
place_edges();
color_graph();
print_data();
}