Cod sursa(job #1238270)

Utilizator hohoho97Valentin Nita hohoho97 Data 6 octombrie 2014 11:15:05
Problema Salvare Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 8.39 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <stack>
#include <vector>
#include <set>

using namespace std;

class Edge
{
private:
	unsigned first;
	unsigned second;
	double weight;

public:
	Edge(unsigned = 0, unsigned = 0, double = 0);
	unsigned from() const;
	unsigned to() const;
	double length() const;
	bool operator< (const Edge&) const;
	bool operator> (const Edge&) const;
	bool operator<= (const Edge&) const;
	bool operator>= (const Edge&) const;
	bool operator== (const Edge&) const;
	bool operator!= (const Edge&) const;
};

class DWGraph
{
private:
	vector<multiset<Edge> > vertices;

public:
	DWGraph(unsigned = 1024);
	unsigned size() const;
	void addVertex();
	void edge(unsigned, unsigned, double);
	const multiset<Edge>& adj(unsigned) const;
	unsigned degree(unsigned) const;
};

Edge::Edge(unsigned from, unsigned to, double length)
{
	this->first = from;
	this->second = to;
	this->weight = length;
}

unsigned Edge::from() const
{
	return this->first;
}

unsigned Edge::to() const
{
	return this->second;
}

double Edge::length() const
{
	return this->weight;
}

bool Edge::operator< (const Edge& other) const
{
	return this->weight < other.weight;
}

bool Edge::operator> (const Edge& other) const
{
	return this->weight > other.weight;
}

bool Edge::operator<= (const Edge& other) const
{
	return this->weight <= other.weight;
}

bool Edge::operator>= (const Edge& other) const
{
	return this->weight >= other.weight;
}

bool Edge::operator== (const Edge& other) const
{
	return this->weight == other.weight;
}

bool Edge::operator!= (const Edge& other) const
{
	return this->weight != other.weight;
}

DWGraph::DWGraph(unsigned vertices)
{
	this->vertices.resize(vertices);
}

unsigned DWGraph::size() const
{
	return this->vertices.size();
}

void DWGraph::addVertex()
{
	this->vertices.push_back(multiset<Edge>());
}

void DWGraph::edge(unsigned from, unsigned to, double weight)
{
	this->vertices.at(from).insert(Edge(from, to, weight));
}

const multiset<Edge>& DWGraph::adj(unsigned vertex) const
{
	return this->vertices.at(vertex);
}

unsigned DWGraph::degree(unsigned vertex) const
{
	return this->vertices.at(vertex).size();
}

template <class keyType>
class IndexedMinPQ
{
private:
	const unsigned Nmax;
	unsigned n;
	vector<unsigned> pq;
	vector<unsigned> qp;
	vector<keyType> keys;

	const unsigned no_key = 0;

	void swap(unsigned i, unsigned j)
	{
		std::swap(pq[i], pq[j]);
		qp[pq[i]] = i;
		qp[pq[j]] = j;
	}

	bool greater(unsigned i, unsigned j)
	{
		return keys[pq[i]] > keys[pq[j]];
	}

	void sink(unsigned i)
	{
		unsigned j = i << 1;
		while (j <= n)
		{
			if (j + 1 <= n)
			{
				if (greater(j, j + 1))
				{
					++j;
				}
			}
			if (greater(i, j))
			{
				swap(i, j);
				i = j;
				j <<= 1;
			}
			else break;
		}
	}

	void swim(unsigned i)
	{
		unsigned j = i >> 1;
		while (j > 0)
		{
			if (greater(j, i))
			{
				swap(i, j);
				i = j;
				j >>= 1;
			}
			else break;
		}
	}

public:
	IndexedMinPQ(unsigned max) : Nmax(max)
	{
		n = 0;
		pq.resize(Nmax + 1, no_key);
		qp.resize(Nmax + 1, no_key);
		keys.resize(Nmax + 1);
	}

	bool push(unsigned index, const keyType& key)
	{
		if (!contains(index))
		{
			n++;
			pq[n] = index;
			qp[index] = n;
			keys[index] = key;
			swim(n);
			return true;
		}
		else return false;
	}

	bool contains(unsigned index) const
	{
		return qp[index] != no_key;
	}

	bool changeKey(unsigned index, const keyType& key)
	{
		if (contains(index))
		{
			keys[index] = key;
			swim(qp[index]);
			sink(qp[index]);
			return true;
		}
		else return false;
	}

	unsigned topIndex() const
	{
		return pq[1];
	}

	const keyType& topKey() const
	{
		return keys[pq[1]];
	}

	bool pop()
	{
		if (!empty())
		{
			unsigned min = pq[1];
			swap(1, n);
			pq[n] = no_key;
			qp[min] = no_key;
			n--;
			sink(1);
			return true;
		}
		else return false;
	}

	unsigned size() const
	{
		return n;
	}

	bool empty() const
	{
		return n == 0;
	}
};

//class Dijkstra
//{
//private:
//	vector<int> from;
//	vector<double> dist;
//	vector<bool> marked;
//
//	const double infinit = 202390219784947236478923467894687.01;
//
//public:
//	Dijkstra(const DWGraph& g, int begin)
//	{
//		from.resize(g.size(), -1);
//		dist.resize(g.size(), infinit);
//		marked.resize(g.size(), false);
//		dist[begin] = 0;
//
//		IndexedMinPQ<double> pq(g.size());
//		pq.push(begin, 0);
//		while (!pq.empty())
//		{
//			int vertex = pq.topIndex();
//			pq.pop();
//			marked[vertex] = true;
//			for (const Edge& e: g.adj(vertex))
//			{
//				int v = e.to();
//				if (!marked[v])
//				{
//					double alt = dist[vertex] + e.length();
//					if (alt < dist[v])
//					{
//						dist[v] = alt;
//						from[v] = vertex;
//						if (!pq.changeKey(v, alt))
//						{
//							pq.push(v, alt);
//						}
//					}
//				}
//			}
//		}
//	}
//
//	double shortestPath(int begin, int end) // atat de gresit...
//	{
//        double ans = 0;
//        while (end != -1 && from[end] != begin)
//        {
//            ans += dist[end];
//            end = from[end];
//        }
//        ans += from[begin];
//
//        return ans;
//	}
//};

class DFS
{
private:
    int Mdepth;
    vector<bool> marked;

public:
    DFS(const DWGraph& g, int index)
    {
        marked.resize(g.size(), false);

        stack<int> st;
        st.push(index);
        marked[index] = true;

        vector<int> depth(g.size(), 0);
        while (!st.empty())
        {
            int v = st.top();
            st.pop();

            for (const Edge& e: g.adj(v))
            {
                if (!marked[e.to()])
                {
                    st.push(e.to());
                    marked[e.to()] = true;
                    depth[e.to()] = depth[v] + 1;
                }
            }
        }
        Mdepth = *max_element(depth.begin(), depth.end());
    }

    int getDepth()
    {
        return Mdepth;
    }
};

class AltDFS
{
private:
    int Mdepth;
    vector<bool> marked;

public:
    AltDFS(const DWGraph& g, const vector<bool>& spitale, int index)
    {
        marked.resize(g.size(), false);

        stack<int> st;
        st.push(index);
        marked[index] = true;

        vector<int> depth(g.size(), 0);
        while (!st.empty())
        {
            int v = st.top();
            st.pop();

            for (const Edge& e: g.adj(v))
            {
                if (spitale[e.to()])
                    continue;
                if (!marked[e.to()])
                {
                    st.push(e.to());
                    marked[e.to()] = true;
                    depth[e.to()] = depth[v] + 1;
                }
            }
        }
        Mdepth = *max_element(depth.begin(), depth.end());
    }

    int getDepth()
    {
        return Mdepth;
    }
};

int main()
{
    ifstream in("salvare.in");
    ofstream out("salvare.out");

//    int n, m, k;
//
//    in >> n >> m >> k;
//
//    DWGraph g(n);
//    int a, b, c;
//    for (int i = 0; i < m; i++)
//    {
//        in >> a >> b >> c;
//        g.edge(a - 1, b - 1, c);
//        g.edge(b - 1, a - 1, c);
//    }
//
//    Dijkstra d(g, 0);
//
//    for (int i = 0; i < k; i++)
//    {
//        in >> a >> b;
//        out << d.shortestPath(a - 1, b - 1) << '\n';
//    }

    int n, k;

    in >> n >> k;

    DWGraph g(n + 1);

    int a, b;
    for (int i = 0; i < n; i++)
    {
        in >> a >> b;
        g.edge(a, b, 1);
        g.edge(b, a, 1);
    }

    IndexedMinPQ<int> pq(n + 1);
    for (int i = 1; i <= n; i++)
    {
        pq.push(i, DFS(g, i).getDepth());
    }

    vector<bool> spitale(n + 1);
    for (int i = 0; i < k; i++)
    {
        spitale[pq.topIndex()] = true;
        pq.pop();
    }

    int MaxD = 0;
    for (int i = 1; i <= n; i++)
    {
        if (spitale[i])
        {
            int ans = AltDFS(g, spitale, i).getDepth();
            if (ans > MaxD)
                MaxD = ans;
        }
    }

    out << MaxD << endl;
    for (int i = 1; i <= n; i++)
    {
        if (spitale[i])
        {
            out << i << ' ';
        }
    }

    in.close();
    out.close();
}