Shuseki Kingdom is the world's leading nation for innovation and technology. There are n cities in the kingdom, numbered from 1 to n.
Thanks to Mr. Kitayuta's research, it has finally become possible to construct teleportation pipes between two cities. A teleportation pipe will connect two cities unidirectionally, that is, a teleportation pipe from city x to city y cannot be used to travel from city y to city x. The transportation within each city is extremely developed, therefore if a pipe from city x to city yand a pipe from city y to city z are both constructed, people will be able to travel from city x to city z instantly.
Mr. Kitayuta is also involved in national politics. He considers that the transportation between the m pairs of city (ai, bi) (1 ≤ i ≤ m) is important. He is planning to construct teleportation pipes so that for each important pair (ai, bi), it will be possible to travel from city ai to city bi by using one or more teleportation pipes (but not necessarily from city bi to city ai). Find the minimum number of teleportation pipes that need to be constructed. So far, no teleportation pipe has been constructed, and there is no other effective transportation between cities.
The first line contains two space-separated integers n and m (2 ≤ n ≤ 105, 1 ≤ m ≤ 105), denoting the number of the cities in Shuseki Kingdom and the number of the important pairs, respectively.
The following m lines describe the important pairs. The i-th of them (1 ≤ i ≤ m) contains two space-separated integers aiand bi (1 ≤ ai, bi ≤ n, ai ≠ bi), denoting that it must be possible to travel from city ai to city bi by using one or more teleportation pipes (but not necessarily from city bi to city ai). It is guaranteed that all pairs (ai, bi) are distinct.
Print the minimum required number of teleportation pipes to fulfill Mr. Kitayuta's purpose.
4 5 1 2 1 3 1 4 2 3 2 4
3
4 6 1 2 1 4 2 3 2 4 3 2 3 4
4
题意:其实看图片就知道题意,就是给出n个点及m条有向边,然后用尽量少的边去代替使得输入的边能直接或间接到达。
思路:一开始以为解为n-连通块的个数+环,不过这样会一直错在第八组,因为没必要加多余的环,后来发现连通块里所有点连成一条最长链,再首尾相连形成环,即可满足取得最少的边。
求连通块个数可用并查集,求环可用强连通分量tarjan算法,不过用这个算法太大材小用了,只要dfs判是否存在环就行了
#include<stdio.h>
#include<string.h>
#include <iostream>
#include <algorithm>
#define MAXNODE 100009
using namespace std;
struct Node{
int to;
Node *next;
}*p,*head[MAXNODE];
int index,n;
int dfn[MAXNODE],low[MAXNODE];
int stack[MAXNODE],top;
bool instack[MAXNODE];
int ans=0,res=0;
int f[MAXNODE],cou[MAXNODE],cyc[MAXNODE];
void add(int from,int to){
p=(Node*)malloc(sizeof(Node));
p->to=to,p->next=head[from],head[from]=p;
}
int find(int x){
if(f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
void Union(int a,int b){
int f1=find(a);
int f2=find(b);
if(f1!=f2){
cou[f1]+=cou[f2];
f[f2]=f1;
}
}
void tarjan(int u)
{
int v;
dfn[u]=low[u]=++index;
instack[u]=true;
stack[top++]=u;
for (Node *p=head[u];p;p=p->next)
{
v=p->to;
if (!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if (instack[v])
low[u]=min(low[u],dfn[v]);
}
if (low[u]==dfn[u])
{
int flag=0;
do
{
v=stack[--top];
instack[v]=false;
flag++;
}
while (u!=v);
if(flag>1&&!cyc[find(u)]) cyc[find(u)]=1,ans++;
}
}
void slove(){
top=index=0;
memset(dfn,0,sizeof(dfn));
for(int i=1;i<=n;i++)
if(!dfn[i]&&!cyc[find(i)])
tarjan(i);
}
void init(){
memset(head,0,sizeof(head));
for(int i=1;i<=n;i++)
f[i]=i,cou[i]=1;
}
int main(void){
int m;
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
Union(u,v);
}
slove();
for(int i=1;i<=n;i++)
if(find(i)==i)
res+=cou[i]-1;
printf("%d\n",res+ans);
return 0;
}