求助大佬 #2 #11WA
查看原帖
求助大佬 #2 #11WA
389609
Future_zxs楼主2022/6/19 23:31

WA掉#2 #11

感觉思路比较清晰,先Tarjan标记桥,再去桥缩点建新图,最后加桥记录叶子数(虽然比较麻烦),但不知道哪里错了,哪位大佬能帮帮蒟蒻

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define maxn 5010
#define maxm 20010

using namespace std;

inline int read()
{
	int x = 0;
	char c = getchar();
	while(c<'0'||c>'9') {c = getchar();}
	while(c>='0'&&c<='9') {x = (x<<1)+(x<<3)+c-'0'; c = getchar();}
	return x;
}

int n, m, cnt, t;
int color, ans;
int co[maxn]; //新图的点 
int first[maxn];
int head[maxn];
int dfn[maxn];
int low[maxn];
int fa[maxn];  
int leaf[maxn];
bool vis[maxn];
bool mark[maxm]; //标记桥 
struct Node
{
	int from;
	int to;
	int next;
}edge[maxm], e[maxm];

void add(int u, int v)
{
	edge[++cnt].from = u;
	edge[cnt].to = v;
	edge[cnt].next = first[u];
	first[u] = cnt;
}

void Tarjan(int u)
{
	dfn[u] = low[u] = ++t;
	for(int i = first[u]; i; i = edge[i].next)
	{
		int v = edge[i].to;
		if(!dfn[v])
		{
			fa[v] = u; //防止更新成父节点的low 
			Tarjan(v);
			low[u] = min(low[u], low[v]);
			if(low[v] > dfn[u])
			mark[i] = 1; //标记桥 
		}
		else if(v != fa[u])
		low[u] = min(low[u], dfn[v]);
	}
}

void dfs(int x) //缩点 
{
	vis[x] = 1;
	co[x] = color;
	for(int i = first[x]; i&&((!mark[i])&&(!mark[i^1])); i = edge[i].next)
	{
		int y = edge[i].to;
		if(!vis[y]) dfs(y);
	}
}

int main()
{
	n = read(); m = read();
	cnt = 1;
	for(int i = 1; i <= m; i++)
	{
		int u = read();
		int v = read();
		add(u, v);
		add(v, u);
	}
	for(int i = 1; i <= n; i++)
	if(!dfn[i]) Tarjan(i);
	
	for(int i = 1; i <= n; i++) //去掉桥并查集建新图 
	if(!vis[i])
	{
		color++;
		dfs(i);
	}
	
	for(int i = 2; i <= cnt; i++) //加入桥 
	{
		if(!mark[i]) continue;
		int x = edge[i].from;
		int y = edge[i].to;
		leaf[co[x]]++;
		leaf[co[y]]++;
	}

	for(int i = 1; i <= color; i++)
	if(leaf[i] == 1) ans++;
	printf("%d\n", (ans+1)/2);
	
	return 0;
}



2022/6/19 23:31
加载中...