点击打开链接
求添加最大的边数使得整个图还不是强连通图
只要还有两个连通分量即可。
全部边数-当前边数取最值即可。
#include #include #include #include #include #include #include #include using namespace std; #include #include #include #include #include #include #define cler(arr, val) memset(arr, val, sizeof(arr)) typedef long long LL; const int MAXN = 111410; const int MAXM = 140000; const int INF = 0x3f3f3f3f; const LL mod = 10000007; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int n, m;//n m 为点数和边数 struct Edge{ int from, to, nex; bool sign;//是否为桥 }edge[MAXM<<1]; int head[MAXN], edgenum; void add(int u, int v){//边的起点和终点 Edge E={u, v, head[u], false}; edge[edgenum] = E; head[u] = edgenum++; } int num[MAXN]; int DFN[MAXN], Low[MAXN], Stack[MAXN], top, Time; //Low[u]是点集{u点及以u点为根的子树} 中(所有反向弧)能指向的(离根最近的祖先v) 的DFN[v]值(即v点时间戳) int taj;//连通分支标号,从1开始 int Belong[MAXN];//Belong[i] 表示i点属于的连通分支 bool Instack[MAXN]; vector bcc[MAXN]; //标号从1开始 void tarjan(int u ,int fa) { DFN[u] = Low[u] = ++ Time ; Stack[top ++ ] = u ; Instack[u] = 1 ; for (int i = head[u] ; ~i ; i = edge[i].nex ) { int v = edge[i].to; if(DFN[v] == -1) { tarjan(v , u); Low[u] = min(Low[u] ,Low[v]) ; if(DFN[u] < Low[v]) { edge[i].sign = 1;//为割桥 } } else if(Instack[v]) { Low[u] = min(Low[u] ,DFN[v]) ; } } if(Low[u] == DFN[u]) { int now; taj ++ ; bcc[taj].clear(); do{ now = Stack[-- top] ; Instack[now] = 0 ; Belong [now] = taj ; num[taj]++; bcc[taj].push_back(now); }while(now != u) ; } } void tarjan_init(int all){ memset(DFN, -1, sizeof(DFN)); memset(Instack, 0, sizeof(Instack)); cler(num,0); top = Time = taj = 0; for(int i=1;i<=all;i++) if(DFN[i]==-1 ) tarjan(i, i); //注意开始点标!!! } vectorG[MAXN]; int du[MAXN]; void suodian(){ memset(du, 0, sizeof(du)); for(int i = 1; i <= taj; i++) G[i].clear(); for(int i = 0; i < edgenum; i++) { int u = Belong[edge[i].from], v = Belong[edge[i].to]; if(u!=v) { G[u].push_back(v), du[v]++; } } } void init(){memset(head, -1, sizeof(head)); edgenum=0;} int main() { int t,cas=1; cin>>t; while(t--) { cin>>n>>m; init(); int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y); } tarjan_init(n); suodian(); printf("Case %d: ",cas++); if(taj==1) puts("-1"); else { LL ans=0; for(int i=1;i<=taj;i++) { if(du[i]==0||G[i].size()==0) ans=max(ans,(LL)n*n-(LL)n-(LL)num[i]*(n-num[i])-(LL)m); } cout<