这题用的是求强连通分图的算法Tarjan算法来求的。 用Tarjan算法求每个强连通分图的割点去掉后增加的强连通图数量。取最大的一种, 加上原来的强连通分量的个数, 便是本题的解。要注意在没边的时候ans就是点数 - 1。
<pre name="code" class="cpp">#include <stdio.h>
#include <string.h>#include <stdlib.h>#include <iostream>#include <algorithm>#define mem(a) memset(a, 0, sizeof(a))using namespace std;int dfn[10005], low[10005], vis[10005], flag, po, eg, cut[10005];struct node{int date;node *next;}point[10005];void tarjan(int s){int i;dfn[s] = low[s] = ++flag;vis[s] = 1;node *q;q = point[s].next;while(q){if(vis[q->date] == 0){tarjan(q->date);if(dfn[s] <= low[q->date])cut[s]++; // 增加的强连通图数量。low[s] = min(low[s], low[q->date]);}else{low[s] = min(low[s], dfn[q->date]);}q = q->next; }}int main(int argc, char *argv[]){int i, j, k, res, ans;for(;;){mem(dfn);mem(low);mem(vis);mem(cut);flag = 0;res = 0;ans = 0;scanf("%d%d",&po, &eg);if(po == 0&&eg == 0)break;if(eg == 0){printf("%d\n", po - 1);continue;}for(i = 0;i < po;i++){point[i].next = 0;}for(i = 0;i < eg;i++){scanf("%d%d",&j, &k); node *q; q = (node*)malloc(sizeof(node)); q->date = j; q->next = point[k].next; point[k].next = q; node *p; p = (node*)malloc(sizeof(node)); p->date = k; p->next = point[j].next; point[j].next = p;}for(i = 0;i < po;i++){if(vis[i] == 0){res++;tarjan(i); cut[i]--; // 因为本来就是一个, 所以要减一。}}for(i = 0;i < po;i++){if(ans < cut[i])ans = cut[i];}printf("%d\n", ans + res);}return 0;}