题意:问加多少边后图会变成强联通分量为1的图
思路:简单的强联通,缩点后找入度和出度就行了,水题
#include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int maxn=20010; vector<int> G[maxn]; vector<int> rG[maxn]; vector<int> vs; bool used[maxn]; int cmp[maxn],V; void add_edge(int from,int to){ G[from].push_back(to); rG[to].push_back(from); } void dfs(int v){ used[v]=1; for(int i=0;i<G[v].size();i++){ if(!used[G[v][i]]) dfs(G[v][i]); } vs.push_back(v); } void rdfs(int v,int k){ used[v]=1; cmp[v]=k; for(int i=0;i<rG[v].size();i++){ if(!used[rG[v][i]]) rdfs(rG[v][i],k); } } int scc(){ memset(used,0,sizeof(used)); vs.clear(); for(int v=0;v<V;v++) if(!used[v]) dfs(v); memset(used,0,sizeof(used)); int k=0; for(int i=vs.size()-1;i>=0;i--){ if(!used[vs[i]]) rdfs(vs[i],k++); } return k; } int A[maxn*3],B[maxn*3]; int in[maxn],out[maxn]; int main(){ int T,m; scanf("%d",&T); while(T--){ scanf("%d%d",&V,&m); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); for(int i=0;i<maxn;i++){ G[i].clear(); rG[i].clear(); } vs.clear(); for(int i=0;i<m;i++){ scanf("%d%d",&A[i],&B[i]); A[i]--;B[i]--; add_edge(A[i],B[i]); } int ans=scc(); if(ans==1){ printf("0\n"); continue; } for(int i=0;i<m;i++){ int a=cmp[A[i]],b=cmp[B[i]]; if(a!=b){ in[b]++;out[a]++; } } int sum1=0,sum2=0; for(int i=0;i<ans;i++){ if(in[i]==0) sum1++; if(out[i]==0) sum2++; } printf("%d\n",max(sum1,sum2)); } return 0; }
时间: 2024-10-10 07:20:22