 /**//*
求最小加边使有向图变为强连通
先缩点,然后计算各个强连通分量的入度为0的个数,出度为0的个数
1) SCC=1, 不需添边
2) 添max( incnt, outcnt )
贪心策略,汇基向点基连边,再添边的连接剩下的点基/汇基即可

*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

const int MAXN=20010;

int n,m;
vector<int>G[2][MAXN];
int ID[MAXN],SCC,flag;
int order[MAXN],cnt;
int in[MAXN],out[MAXN];

 void dfs(int u) {
ID[u]=SCC;
 for(int i=0;i<G[flag][u].size();i++) {
int v=G[flag][u][i];
if(!ID[v])dfs(v);
}
if(flag)order[++cnt]=u;
}

 int main() {
int T,a,b;
scanf("%d",&T);
 while(T--) {
scanf("%d%d",&n,&m);
 for(int i=1;i<=n;i++) {
G[0][i].clear();
G[1][i].clear();
}
 while(m--) {
scanf("%d%d",&a,&b);
G[0][a].push_back(b);
G[1][b].push_back(a);
}
flag=SCC=1;
cnt=0;
memset(ID,0,sizeof(ID));
for(int i=1;i<=n;i++)
if(!ID[i])dfs(i);
flag=SCC=0;
memset(ID,0,sizeof(ID));
 for(int i=cnt;i;i--) {//注意是order[i]
if(ID[order[i]])continue;
SCC++;
dfs(order[i]);
}
 if(SCC==1) {puts("0");continue;}
memset(out,0,sizeof(out));
memset(in,0,sizeof(in));
for(int i=1;i<=n;i++)
 for(int j=0;j<G[0][i].size();j++) {
int v=G[0][i][j];
 if(ID[i]!=ID[v]) {
in[ID[v]]++;
out[ID[i]]++;
}
}
int incnt=0,outcnt=0;
 for(int i=1;i<=SCC;i++) {
if(in[i]==0)incnt++;
if(out[i]==0)outcnt++;
}
printf("%d\n",max(incnt,outcnt));
}
return 0;
}
|
|
常用链接
随笔分类
Links
搜索
最新评论

|
|