hdu终于开服了,这题果断AC,题目大意国王要给城市划分州,要求是如果互相联通的要画在一个州,并且相连两个州之间不能有城市,可以想到是强连通+最小路径覆盖,然后就比较好求解了,注意这里数组要开到100000+不然会WA(之前比赛开5100WA了N次。。血泪史啊。。。)
#include <iostream>
#include <vector>
#include <map>
using namespace std;
const int size = 100100;
vector <int> mapp[size], remapp[size];
vector <int>comp[size];
vector <int>sccindex[size];
map <int, int> mak;
bool visited[size];
int num[size];
int belg[size];
int counter;
int n , m;
bool flag[size];
int match[size];
int edge[5*size][2];
void init()
{
for (int i = 0; i <= n; i ++){
mapp[i].clear(), remapp[i].clear(), comp[i].clear(), sccindex[i].clear();
}
mak.clear();
}
void dfs1(int v)
{
visited[v] = true;
for (int i = 0; i < mapp[v].size(); i ++){
int t = mapp[v][i];
if (!visited[t]){
dfs1(t);
}
}
num[++counter]= v;
}
int kk;
void dfs2(int v)
{
visited[v] = true;
belg[v] = kk;
sccindex[kk].push_back(v);
mak[v] = kk;
for (int i = 0; i < remapp[v].size(); i ++){
int t = remapp[v][i];
if (!visited[t]){
dfs2(t);
}
}
}
void scc()
{
counter = 0;
memset(visited, false, sizeof(visited));
for (int i = 1; i <= n; i ++){
if (!visited[i]){
dfs1(i);
}
}
memset(visited, false ,sizeof(visited));
kk = 0;
for (int i = counter; i >= 1; i --){
int k = num[i];
if (!visited[k]){
visited[k] = true;
++ kk;
dfs2(k);
}
}
}
void compress()
{
for (int i = 1; i <= n; i ++){
for (int j = 0; j < mapp[i].size(); j ++){
if (belg[mapp[i][j]] != belg[i]){
comp[belg[i]].push_back(belg[mapp[i][j]]);
}
}
}
}
bool dfs(int v)
{
for (int i = 0; i < comp[v].size(); i ++){
int k = comp[v][i];
if (flag[k])continue;
flag[k] = true;
if (dfs(match[k]) || !match[k]){
match[k] = v;
return true;
}
}
return false;
}
int main()
{
//freopen("IN.txt", "r", stdin);
//freopen("OUT.txt", "w", stdout);
int t;
scanf("%d", &t);
while (t --){
init();
scanf("%d%d", &n, &m);
int t;
int a, b;
for (int i = 0; i < m; i ++){
scanf("%d%d", &a, &b);
edge[i][0] = a;
edge[i][1] = b;
mapp[a].push_back(b);
remapp[b].push_back(a);
}
scc();
compress();
if (kk == 1){
printf("1\n");
continue;
}
memset(match, 0, sizeof(match));
int counter = 0;
for (int i = 1; i <= kk; i ++){
memset(flag, false, sizeof(flag));
if (dfs(i)){
counter ++;
}
}
printf("%d\n", kk-counter);
}
return 0;
}