题意:n个点,m条边,如果有(u,v),(v,w),那么u点可以传染w点,问你至少要添加多少条边,才能使无论从哪条边出发,都能感染所有点。
题解:当有一个奇环的时候,就能符合题意。所以我们先找出有多少个联通块,ans = 联通块数量-1,如果图中本来不存在奇环,就ans再++。判是否存在奇环用二分图染色。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 5e5+5;
int head[maxn],tot,col[maxn];
bool vis[maxn],flag;
struct node
{
int to,next;
}a[maxn<<1];
void add(int u,int v)
{
a[tot].to = v;
a[tot].next = head[u];
head[u] = tot++;
}
void dfs(int x,int k)
{
vis[x] = true;
for(int i=head[x]; i!=-1; i=a[i].next)
{
int v = a[i].to;
if(!col[v])
{
col[v] = -k;
}
else
{
if(col[v] != -k)
{
flag = true;//存在奇环
}
}
if(!vis[v])
dfs(v,-k);
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
for(int i=1; i<=m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
int cnt = 0;
for(int i=1; i<=n; i++)
{
if(!vis[i])
{
cnt++;
col[i] = 1;
dfs(i,1);
}
}
if(!flag)
cnt++;
printf("%d",cnt-1);
}