2017年多校賽第九場 1005 FFF at Valentine(縮點+拓撲排序)
阿新 • • 發佈:2018-12-24
其實縮點很容易想到,就是不怎麼會用拓撲排序所以一直卡著判斷這個地方。
程式碼如下:
#include <stdio.h> #include <string.h> #include <vector> #include <stack> #include <algorithm> #include <iostream> #include<queue> using namespace std; const int N = 1005; // 點的最大個數 stack <int> sta; // 存放遍歷了的點 vector <int> edge[N]; // 記錄每個點能到達哪些點 int dfn[N]; // 第幾個遍歷 int low[N]; // 根是多少 int key[N]; // 三種狀態,在佇列為2,不在佇列為0,已經訪問但不在棧中為1 vector <int> com[N]; // 每個com裡面都是一個強聯通分量,最多有N個 int incom[N]; // 記錄每個點在第幾個強聯通分量裡面 int ind, com_num; // 下標, 強聯通個數 int n, m; // 點數和邊數 int in[N]; vector <int> G[N]; void init() { memset(dfn, -1, sizeof(dfn)); memset(low, -1, sizeof(low)); memset(key, 0, sizeof(key)); memset(in, 0, sizeof(in)); ind = com_num = 0; for(int i = 0; i <= n; i++) { edge[i].clear(); G[i].clear(); } while(!sta.empty()) sta.pop(); } void tarjan(int u) { int v; key[u] = 2; //放入棧的標記 low[u] = dfn[u] = ind++; //u是第ind個被遍歷到 sta.push(u); //遍歷到的加入棧中 for(int i = 0; i < edge[u].size(); i++) { v = edge[u][i]; if(dfn[v] == -1) //v這個點還未遍歷到,則遍歷 { tarjan(v); low[u] = min(low[u], low[v]); //取能遍歷到的最小的根序號 } else if(key[v] == 2) //v這個點已經遍歷到且仍存於棧中,則取他們遍歷順序的較小值 low[u] = min(low[u], dfn[v]); } if(low[u] == dfn[u]) //如果某個點遍歷下去又回到了這個u,即為強聯通,會使得該情況成立,則有 { while(!sta.empty()) //把棧中的點取出,直至取到u { int j = sta.top(); sta.pop(); key[j] = 1; //這個點已經遍歷過且不需再遍歷 incom[j] = com_num; //記錄下j在第com個強連通分量集合裡面 if (j == u) break; } com_num++; //一個強聯通分量產生 } } queue <int> q; int main() { int T; scanf("%d", &T); int a, b, m; while(T--) { scanf("%d%d", &n, &m); init(); for(int i = 1; i <= m; i++) { scanf("%d%d", &a, &b); edge[a].push_back(b); } for(int i = 1; i <= n; i++) if(dfn[i] == -1) tarjan(i); for(int i = 1; i <= n; i++) { for(int j = 0; j < edge[i].size(); j++) { int v = edge[i][j]; if(incom[i] == incom[v]) continue; G[incom[i]].push_back(incom[v]); in[incom[v]]++; } } for(int i = 0; i < com_num; i++) if(in[i] == 0) q.push(i); bool flag = 0; while(!q.empty()) { if(q.size() > 1) flag = 1; int u = q.front(); q.pop(); for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; in[v]--; if(in[v] == 0) q.push(v); } } if(!flag) { printf("I love you my love and our love save us!\n"); } else { printf("Light my fire!\n"); } } return 0; }