tarjan标准题。 直接tarjan即可。
思考一个问题:添加多少个边让图变为连通图。
Test 1: TEST OK [0.003 secs, 3512 KB] Test 2: TEST OK [0.003 secs, 3380 KB] Test 3: TEST OK [0.003 secs, 3512 KB] Test 4: TEST OK [0.005 secs, 3512 KB] Test 5: TEST OK [0.005 secs, 3512 KB] Test 6: TEST OK [0.005 secs, 3512 KB] Test 7: TEST OK [0.005 secs, 3512 KB] Test 8: TEST OK [0.008 secs, 3512 KB] Test 9: TEST OK [0.008 secs, 3512 KB] Test 10: TEST OK [0.005 secs, 3512 KB] Test 11: TEST OK [0.005 secs, 3512 KB]
/* TASK:schlnet LANG:C++ */ #include <iostream> #include <cstdio> #include <vector> using namespace std; vector<int>G[200]; int n; int DFN[200] = {0}, LOW[200] = {0}; int instack[200] = {0}, my_stack[200] = {0}; int belong[200] = {0}; int Stop = 0, din = 0, count = 0; void tarjan(int k) { LOW[k] = DFN[k] = ++ din; my_stack[++ Stop] = k; instack[k] = 1; for (int i = 0; i != G[k].size(); ++ i) { int will = G[k][i]; if (!DFN[will]) { tarjan(will); LOW[k] = min(LOW[k], LOW[will]); } else if (instack[will]) LOW[k] = min(LOW[k], DFN[will]); } if (LOW[k] == DFN[k]) { int tmp; ++ count; do { tmp = my_stack[Stop --]; instack[tmp] = 0; belong[tmp] = count; }while (tmp != k); } } int rudu[200] = {0}, chudu[200]={0}; int main() { //freopen("schlnet.in", "r", stdin); //freopen("schlnet.out","w",stdout); cin >> n; for (int i = 0; i != n; ++ i) { while (1) { int tmp; cin >> tmp; if (!tmp) break;; G[i].push_back(tmp - 1); } } for (int i = 0; i != n; ++ i) if (!DFN[i]) tarjan(i); for (int i = 0; i != n; ++ i) for (int j = 0; j != G[i].size(); ++ j) { int will = G[i][j]; if (belong[i] == belong[will]) continue; ++ rudu[belong[will]]; ++ chudu[belong[i]]; } int ans1 = 0, ans2 = 0;//ans1 几个地方发放就可以了 ans2要连接几个 for (int i = 1; i <= count; ++ i) { if (!chudu[i]) ++ans2; if (!rudu[i]) ++ ans1; } cout<<ans1<<endl; if (count > 1)cout<<max(ans1, ans2)<<endl; else cout<<0<<endl; return 0; }