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);
}
}