Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <vector>
- #include <cstdio>
- #include <iostream>
- #include <set>
- using namespace std;
- void dfs_harvest(int vertex, vector<bool>&visited, vector<vector<int> >&adj, vector<int>&segment){
- if (visited[vertex]) return;
- visited[vertex] = true;
- segment.push_back(vertex);
- for (int i = 0; i < adj[vertex].size(); i++){
- dfs_harvest(adj[vertex][i], visited, adj, segment);
- }
- }
- vector<vector<int> > find_segments(int n, vector<vector<int> >&adj){
- vector<bool>visited(n,false);
- vector<vector<int> > result;
- for (int vertex = 0; vertex < n; vertex++){
- if (visited[vertex]) continue;
- vector<int>segment;
- dfs_harvest(vertex, visited, adj, segment);
- result.push_back(segment);
- }
- return result;
- }
- void find_bridges(int u, vector<bool>&visited, vector<int>& disc, vector<int>&low, vector<int>&parent, vector<vector<int> >&adj, vector<pair<int, int> >&bridges){
- static int time = 0;
- visited[u] = true;
- disc[u] = low[u] = ++time;
- for (int i = 0; i < adj[u].size(); i++)
- {
- int v = adj[u][i];
- if (!visited[v])
- {
- parent[v] = u;
- find_bridges(v, visited, disc, low, parent, adj, bridges);
- low[u] = min(low[u], low[v]);
- if (low[v] > disc[u]){
- bridges.push_back(make_pair(u,v));
- }
- }
- else if (v != parent[u])
- low[u] = min(low[u], disc[v]);
- }
- }
- int main(int argc, char const *argv[])
- {
- int n, m;
- scanf("%d %d", &n, &m);
- vector<vector<int> >adj;
- for (int i = 0; i < n; i++){
- vector<int>t;
- adj.push_back(t);
- }
- set<pair<int, int> >adj_set;
- for (int i = 0; i < m; i++){
- int v1,v2;
- scanf("%d %d", &v1, &v2);
- v1--; v2--;
- adj[v1].push_back(v2);
- adj[v2].push_back(v1);
- adj_set.insert(make_pair(v1,v2));
- adj_set.insert(make_pair(v2,v1));
- }
- vector<pair<int, int> >bridges;
- vector<bool>visited(n, false);
- vector<bool>visited2(n, false);
- vector<int>disc(n,0);
- vector<int>parent(n, -1);
- vector<int>low(n,0);
- for (int i = 0; i < n; i++){
- find_bridges(i, visited, disc, low, parent, adj, bridges);
- }
- vector<int>bridge_endpoint(n,0);
- for (int i = 0; i < bridges.size(); i++){
- int v1 = bridges[i].first;
- int v2 = bridges[i].second;
- bridge_endpoint[v1] += 1;
- bridge_endpoint[v2] += 1;
- adj_set.erase(adj_set.find(make_pair(v1,v2)));
- adj_set.erase(adj_set.find(make_pair(v2,v1)));
- }
- vector<vector<int> >adj_b;
- for (int i = 0; i < n; i++){
- vector<int>t;
- adj_b.push_back(t);
- }
- set<pair<int, int> >::iterator it;
- for (it = adj_set.begin(); it != adj_set.end(); ++it){
- int v1 = (*it).first;
- int v2 = (*it).second;
- adj_b[v1].push_back(v2);
- }
- long long options = 1;
- int shops_needed = 0;
- vector<vector<int> >blocks = find_segments(n, adj_b);
- for (int i = 0; i < blocks.size(); i++){
- bool ok = true;
- for (int j = 0; j < blocks[i].size(); j++){
- if (bridge_endpoint[blocks[i][j]] > 1) ok = false;
- }
- if (ok){
- shops_needed ++;
- options = (options * blocks[i].size()) % 1000000007ll;
- }
- }
- printf("%d %lld\n", shops_needed, options);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement