Loading

POJ 3697 USTC campus network(BFS 删边)

POJ 3697 USTC campus network(BFS 删边)

题意:

​ 有一张图,每个点\(n \le 10000\)之间都有一条边。现在删去若干条边\(m \le 1000000\),请问还有多少点是联通的。

思路:

​ 我能想到最朴素的方法就是,建出一张不含这些被删去边的图,跑一下就知道有多少点联通了。这个想法第一是很难直接实现,第二是时间复杂度很高。所以我们可以想一下用什么来等效替代这个建图的效果。我们可以用BFS来模拟这个建边的过程,若是发现要建的边是被删去的,就不做操作,不然连出一条边。时间复杂度是\(O(n^2+m)\),需要用快读才能过。

实现:

typedef long long ll;
const int N = 10005;
int n, m;
vector<int> g[N];
int vis[N];
int del[N];

void read(int &num)
{
    int s = 0; char ch = getchar();
    while(ch < '0' || ch > '9') ch = getchar();
    while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
    num = s;
}

int bfs()
{
	int res = 0;
	for(int i = 1; i <= n; i ++)	vis[i] = 0, del[i] = -1;
	queue<int> q;
	vis[1] = 1;
	q.push(1);

	while(q.size())
	{
		int u = q.front();
		q.pop();

		for(int i = 0; i < (int)g[u].size(); i ++)
		{
			int v = g[u][i];
			del[v] = u;
		}

		for(int i = 1; i <= n; i ++)
		{
			if(del[i] != u && !vis[i]) //没被删的
			{
				vis[i] = 1;
				res ++;
				q.push(i);
			}
		}
	}
	return res;
}

int main()
{
	int id = 1;
	while(~scanf("%d%d", &n, &m))
	{
		if(!n && !m)	break;
		for(int i = 1; i <= n; i ++)	g[i].clear();

		while(m --)
		{
			int u, v;
			read(u); read(v);
			g[u].push_back(v);
			g[v].push_back(u);
		}
		int res = bfs();
		printf("Case %d: %d\n", id ++, res);
	}
}
posted @ 2022-10-05 21:39  DM11  阅读(17)  评论(0编辑  收藏  举报