CCCC L2-013. 红色警报 连通分量

题解:将问题转化成连通分量。每次失去一座城市,切断其所有的边,算一次现在的连通分量。若增量大于1,则发出警报。

    至于如何算连通分量,直接用tarjan模板

坑://我昨天晚上半夜敲的模板,把一个算所有环中最短环的tarjan模板 直接贴上去了,一直不过,还XJB改了会儿233(现在90行的代码逛逛B站随便改改就ac了2333)

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<iostream> 
 3 #include<vector>
 4 #include<queue>
 5 #include<map>
 6 #include<cmath>
 7 #include<stack>
 8 #include<string.h>
 9 #include<set>
10 using namespace std;
11 const int maxn = 500 + 5;
12 vector<int> E[maxn];
13 int dfn[maxn], low[maxn], tot, n, ans =0, vis[maxn];
14 stack<int> S;
15 void init() {
16     for (int i = 0; i < maxn; i++) vis[i] = dfn[i] = low[i] = 0;
17     tot = 0;
18     ans = 0;
19 }
20 void tarjan(int x) {
21     low[x] = dfn[x] = ++tot;
22     S.push(x); vis[x] = 1;
23     for (int i = 0; i < E[x].size(); i++) {
24         int v = E[x][i];
25         if (!dfn[v]) {
26             tarjan(v);
27             low[x] = min(low[x], low[v]);
28 
29         }
30         else if (vis[x]) {
31             low[x] = min(low[x], dfn[v]);
32         }
33     }
34     if (low[x] == dfn[x]) {
35         //int cnt = 0;
36         while (1) {
37             int now = S.top();
38             S.pop();
39             vis[x] = 0;
40             //cnt++;
41             if (now == x)break;
42         }
43         ans++;
44         //if (cnt > 1)ans = min(ans, cnt);
45     }
46 }
47 set<int> st[maxn];
48 int main() {
49     int m;
50     cin >> n >> m;
51     for (int i = 0; i < n; i++)E[i].push_back(i);
52     for (int i = 1; i <= m; i++) {
53         int x, y;
54         scanf("%d%d", &x, &y);//判重??没用
55         if (st[x].count(y) == 0) { E[x].push_back(y); st[x].insert(y); }
56         if (st[y].count(x) == 0) { E[y].push_back(x); st[y].insert(x); }
57         //E[y].push_back(x);
58     }
59     //n500m5000
60     for (int i = 1; i <= n; i++) {
61         if (!dfn[i])tarjan(i);
62     }
63     int last = ans;
64     int q; cin >> q;
65     
66     for (int j = 1; j <= q; j++) {
67         int x; cin >> x;
68         int ok = 0;
69         for (int i = 0; i < E[x].size(); i++) {
70             int v = E[x][i];
71 //            for (auto t : E[v]) if (t == x)t = -1;//强行去除反向边。
72             for (vector<int>::iterator it = E[v].begin(); it != E[v].end(); it++)if (*it == x) { E[v].erase(it); break; }
73         }
74 
75         E[x].clear();
76         E[x].push_back(x);
77         init();
78         //cout << last<< endl;
79         for (int i = 1; i <= n; i++) {
80             if (!dfn[i])tarjan(i);
81         }
82         if (ans > last + 1) ok = 1;
83         last = ans;
84         if (ok)printf("Red Alert: City %d is lost!
", x);
85         else printf("City %d is lost.
", x);
86     }
87     //cout << ans << endl;
88     if (q == n)cout << "Game Over.";
89     system("pause");
90 }
成功的路并不拥挤,因为大部分人都在颓(笑)
原文地址:https://www.cnblogs.com/SuuT/p/8678176.html