无向图的双连通分量

冗余路径

#include <bits/stdc++.h>
using namespace std;
const int N = 5005, M = 20005;
int n, m, head[N], cnt = -1, scc[N], scc_cnt = 0, siz[N];
vector<int> g[N];
int vis[N], stk[N], hh = 0, dfn[N], low[N], tot = 0, sum = 0;
struct edge
{
	int to, nxt;
}e[M];
void add(int u, int v)
{
	e[++ cnt].nxt = head[u], e[cnt].to = v, head[u] = cnt;
	return ;
}
void tarjan(int x, int from)
{
	dfn[x] = low[x] = ++ tot;
	stk[++ hh] = x, vis[x] = 1;
	for (int i = head[x]; i != -1; i = e[i].nxt)
	{
		int y = e[i].to;
		if(!dfn[y])
		{
			tarjan(y, i);
			low[x] = min(low[x], low[y]);	
		}
		else if(vis[y] && i != (from ^ 1)) low[x] = min(low[x], dfn[y]);
	}
	if(dfn[x] == low[x])
	{
		scc_cnt ++;
		int y;
		do
		{
			y = stk[hh --];
			vis[y] = 0;
			scc[y] = scc_cnt;
		}while(y != x);
	}
	return ;
} 
int main()
{
	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);
	}
	tarjan(1, -1);
	for (int i = 1; i <= n; ++ i)
	{
		for (int j = head[i]; j != -1; j = e[j].nxt)
		{
			int y = e[j].to;
			if(scc[y] == scc[i]) continue;
			siz[scc[y]] ++, siz[scc[i]] ++;
		}
	}
	for (int i = 1; i <= scc_cnt; ++ i) 
	{
		if(siz[i] == 2) sum ++;	
	}
	printf("%d", (sum + 1) / 2);
	return 0;
}

电力

#include <bits/stdc++.h>
using namespace std;
const int N = 10005, M = 30005;
int n, m, head[N], cnt = - 1, d[N], dfn[N], low[N], tot = 0, scc_cnt = 0, scc[N], k = 0, ans = 0;
int stk[N], hh = 0, root = 0;
struct edge
{
	int to, nxt;
}e[M];
void add(int u, int v)
{
	e[++ cnt].to = v, e[cnt].nxt = head[u], head[u] = cnt;
	return ;
}
void tarjan(int x, int from)
{
	dfn[x] = low[x] = ++ tot;
	stk[++ hh] = x;
	int num = 0;
	for (int i = head[x]; i != - 1; i = e[i].nxt)
	{
		int y = e[i].to;
		if(!dfn[y])
		{
			tarjan(y, i);
			low[x] = min(low[x], low[y]);
			if(low[y] >= dfn[x]) num ++;
		}
		else if(i != (from ^ 1))
		{
			low[x] = min(low[x], dfn[y]);
		}
	}
	if(x != root) num ++;
	if(low[x] == dfn[x])
	{
		int y;
		scc_cnt ++;
		do
		{
			y = stk[hh --];
			scc[y] = scc_cnt;
		}while(y != x);
	}
	ans = max(ans, num);
	return ;
}
int main()
{
	while(true)	
	{
		scanf("%d %d", &n, &m);
		if(n == 0 && m == 0) break;
		for (int i = 0; i <= n; ++ i) head[i] = -1, dfn[i] = low[i] = 0, d[i] = 0, scc[i] = 0;
		tot = 0, cnt = - 1, scc_cnt = 0, k = 0, ans = 0;
		for (int i = 1; i <= m; ++ i)
		{
			int u, v;
			scanf("%d %d", &u, &v);
			add(u, v), add(v, u);
		}
		for (int i = 0; i <= n - 1; ++ i) if(!dfn[i]) root = i, tarjan(i, -1), k ++;
		printf("%d\n", ans + k - 1);
	}
	return 0;
} 

矿场搭建

#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
typedef long long ll;
ll sum1 = 0, sum2 = 1;
struct edge
{
	int to, nxt;
}e[N];
int cnt = -1, tot = 0, dfn[N], low[N], head[N], n = 0, m, T = 0;
int ged[N], sdd_cnt = 0, root = 0, stk[N], hh = 0;
vector<int> sdd[N]; 
void add(int u, int v)
{
	e[++ cnt].nxt = head[u], e[cnt].to = v, head[u] = cnt;
	return ;
}
void tarjan(int x)
{
	dfn[x] = low[x] = ++ tot;
	if(x == root && head[x] == -1)
	{
		sdd[++ sdd_cnt].push_back(x);
		return ;
	}
	stk[++ hh] = x;
	int res = 0;
	for (int i = head[x]; i != - 1; i = e[i].nxt)
	{
		int y = e[i].to;
		if(!dfn[y])
		{
			tarjan(y);
			low[x] = min(low[x], low[y]);
			if(low[y] >= dfn[x]) 
			{
				res ++;
				if(res >= 2 || x != root) ged[x] = 1;
				sdd_cnt ++;
				int u;
				do
				{
					u = stk[hh --];
					sdd[sdd_cnt].push_back(u);
				}while(u != y);
				sdd[sdd_cnt].push_back(x);
			}
		}
		else low[x] = min(low[x], dfn[y]);
	}
	return ;
}
int main()
{
	memset(head, - 1, sizeof head);
	while(scanf("%d", &m) && m)
	{
		T ++;
		for (int i = 1; i <= n; ++ i) head[i] = -1, dfn[i] = 0, low[i] = 0, ged[i] = 0;
		for (int i = 1; i <= sdd_cnt; ++ i) sdd[i].clear();
		cnt = -1, n = 0, sdd_cnt = 0, tot = 0, sum1 = 0, sum2 = 1;
		for (int i = 1; i <= m; ++ i)
		{
			int u, v;
			scanf("%d %d", &u, &v);
			add(u, v);
			add(v, u);
			n = max(n, max(u, v));
		}
		for (int i = 1; i <= n; ++ i) if(!dfn[i]) root = i, tarjan(i), hh = 0; 
		for (int i = 1; i <= sdd_cnt; ++ i)
		{
			int num = 0;
			for (int j = 0; j < sdd[i].size(); ++ j)
			{
				if(ged[sdd[i][j]]) num ++;
			}
			if(num == 0) 
			{
				if(sdd[i].size() == 1) sum1 += 1;
				else sum1 += 2, sum2 = sdd[i].size() * (sdd[i].size() - 1) / 2 * sum2;
			}
			else if(num == 1)
			{
				sum1 += 1, sum2 = sum2 * (sdd[i].size() - 1);
			}
			else if(num == 2)
			{
				
			}
		}
		printf("Case %d: %lld %lld\n", T, sum1, sum2);
	}
}
posted @   Helioca  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
Document
点击右上角即可分享
微信分享提示