AtCoder ABC157D 题解

题目

D - Friend Suggestions

Time Limit: 2 2 2 sec / Memory Limit: 1024 1024 1024 MB / Score: 400 400 400 points

Problem Statement

An SNS has N N N users - User 1 1 1, User 2 2 2, ⋯, User N N N.
Between these N N N users, there are some relationships - M M M friendships and K K K blockships.
For each i = 1 , 2 , ⋯ , M i = 1,2,⋯,M i=1,2,,M, there is a bidirectional friendship between User A i A_i Ai and User B i B_i Bi.
For each i = 1 , 2 , ⋯ , K i = 1,2,⋯,K i=1,2,,K, there is a bidirectional blockship between User C i C_i Ci and User D i D_i Di.
We define User a a a to be a friend candidate for User b b b when all of the following four conditions are satisfied:

  • a ≠ b a≠b a=b.
  • There is not a friendship between User a a a and User b b b.
  • There is not a blockship between User a a a and User b b b.
  • There exists a sequence c 0 , c 1 , c 2 , . . . , c L c_0, c_1, c_2, ..., c_L c0,c1,c2,...,cL consisting of integers between 1 1 1 and N N N (inclusive) such that c 0 = a c_0=a c0=a, c L = b c_L=b cL=b, and there is a friendship between User c i c_i ci and ci+1 for each i = 0 , 1 , ⋯ , L − 1 i = 0,1,⋯,L−1 i=0,1,,L1.

For each user i = 1 , 2 , . . . , N i = 1,2,..., N i=1,2,...,N, how many friend candidates does it have?

Constraints

All values in input are integers.
2 ≤ N ≤ 1 0 5 2\le N\le 10^5 2N105
0 ≤ M ≤ 1 0 5 0\le M\le 10^5 0M105
0 ≤ K ≤ 1 0 5 0\le K\le 10^5 0K105
1 ≤ A i , B i ≤ N 1\le A_i,B_i\le N 1Ai,BiN
A i ≠ B i A_i\ne B_i Ai=Bi
1 ≤ C i , D i ≤ N 1\le C_i,D_i\le N 1Ci,DiN
C i ≠ D i C_i\ne D_i Ci=Di
( A i , B i ) ≠ ( A j , B j )      ( i ≠ j ) (A_i,B_i)\ne (A_j,B_j)~~~~(i≠j) (Ai,Bi)=(Aj,Bj)    (i=j)
( A i , B i ) ≠ ( B j , A j ) (A_i,B_i)\ne (B_j,A_j) (Ai,Bi)=(Bj,Aj)
( C i , D i ) ≠ ( D j , C j )      ( i ≠ j ) (C_i,D_i)\ne (D_j,C_j)~~~~(i≠j) (Ci,Di)=(Dj,Cj)    (i=j)
( A i , B i ) ≠ ( C j , D j ) (A_i,B_i)\ne (C_j,D_j) (Ai,Bi)=(Cj,Dj)
( A i , B i ) ≠ ( D j , C j ) (A_i,B_i)\ne (D_j,C_j) (Ai,Bi)=(Dj,Cj)

Input

Input is given from Standard Input in the following format:

N M K
A1 B1
A2 B2
...
AM BM
C1 D1
C2 D2
...
CK DK

Output

Print the answers in order, with space in between.

Sample Input 1

4 4 1
2 1
1 3
3 2
3 4
4 1

Sample Output 1

0 1 0 1

There is a friendship between User 2 and 3, and between 3 and 4. Also, there is no friendship or blockship between User 2 and 4. Thus, User 4 is a friend candidate for User 2.

However, neither User 1 or 3 is a friend candidate for User 2, so User 2 has one friend candidate.

Sample Input 2

5 10 0
1 2
1 3
1 4
1 5
3 2
2 4
2 5
4 3
5 3
4 5

Sample Output 2

0 0 0 0 0

Everyone is a friend of everyone else and has no friend candidate.

Sample Input 3

10 9 3
10 1
6 7
8 2
2 5
8 4
7 3
10 9
6 4
5 8
2 6
7 5
3 1

Sample Output 3

1 3 5 4 3 3 3 3 1 0

思路

把整个朋友圈拆分为一个个连通子图,再对于每个用户用对应子图节点数-1(本身)-子图中的跟当前用户有friendshipblockship的逐个得到结果

代码

代码也在这里
注意:只能使用C++>=11的编译器才能通过编译。(我提交时用的是 C++14 (GCC 5.4.1) 编译器)

#include 
#include 
#include 
#define maxn 100005
using namespace std;

typedef vector<int>* Graph;

int n, m, k, graphnum[maxn], subgraphsize[maxn];
vector<int> friends[maxn], block[maxn];

template <typename T>
void bfs(const Graph& G, int v, T visit, bool* visited)
{
	queue<int> q;
	q.push(v);
	while(!q.empty())
	{
		int x = q.front(); q.pop();
		if(visited[x]) continue;
		visited[x] = true;
		visit(x);
		for(int it: G[x]) q.push(it);
	}
}

void splitgraph(const Graph& G) // Returns: number of subgraphs
{
	int cnt = 0;
	auto vis = [&cnt](int v) {
		subgraphsize[graphnum[v] = cnt] ++;
	};
	bool* visited = new bool[n];
	// split into subgraphs
	for(int i=0; i<n; i++) visited[i] = false;
	for(int i=0; i<n; i++)
		if(!visited[i])
		{
			bfs(G, i, vis, visited);
			cnt ++;
		}
	delete[] visited;
}

int main(int argc, char** argv)
{
	// Input
	scanf("%d%d%d", &n, &m, &k);
	for(int i=0; i<m; i++)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		friends[--x].push_back(--y);
		friends[y].push_back(x);
	}
	for(int i=0; i<k; i++)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		block[--x].push_back(--y);
		block[y].push_back(x);
	}
	// Split firends into subgraphs
	splitgraph(friends);
	// Count bad (friendships & blockships in current subgraph & itself) for each vertex
	int* badcnt = new int[n];
	for(int i=0; i<n; i++) badcnt[i] = 1; // 1, not 0! (the vertex itself)
	for(int i=0; i<n; i++)
	{
		// Blockship 
		for(int it: block[i])
			if(it > i && graphnum[it] == graphnum[i])
				badcnt[i] ++, badcnt[it] ++;
		// Friendship
		for(int it: friends[i])
			if(it > i && graphnum[it] == graphnum[i])
				badcnt[i] ++, badcnt[it] ++;
	}
	for(int i=0; i<n; i++) printf("%d ", subgraphsize[graphnum[i]] - badcnt[i]);
	putchar('\n');
	delete[] badcnt;
	return 0;
}

你可能感兴趣的:(算法竞赛)