D - Friend Suggestions
Time Limit: 2 2 2 sec / Memory Limit: 1024 1024 1024 MB / Score: 400 400 400 points
题意
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,⋯,L−1.
For each user i = 1 , 2 , . . . , N i = 1,2,..., N i=1,2,...,N, how many friend candidates does it have?
约束
- 输入中所有数都是整数。
- 2 ≤ N ≤ 1 0 5 2\le N\le 10^5 2≤N≤105
- 0 ≤ M ≤ 1 0 5 0\le M\le 10^5 0≤M≤105
- 0 ≤ K ≤ 1 0 5 0\le K\le 10^5 0≤K≤105
- 1 ≤ A i , B i ≤ N 1\le A_i,B_i\le N 1≤Ai,Bi≤N
- 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 1≤Ci,Di≤N
- 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 N~M~K N M K
A 1 B 1 A_1~B_1 A1 B1
A 2 B 2 A_2~B_2 A2 B2
: : :
A M B M A_M~B_M AM BM
C 1 D 1 C_1~D_1 C1 D1
C 2 D 2 C_2~D_2 C2 D2
: : :
C K D K C_K~D_K 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 2 2 and 3 3 3, and between 3 3 3 and 4 4 4. Also, there is no friendship or blockship between User 2 2 2 and 4 4 4. Thus, User 4 4 4 is a friend candidate for User 2 2 2.
However, neither User 1 1 1 or 3 3 3 is a friend candidate for User 2 2 2, so User 2 2 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(本身)-子图中的跟当前用户有friendship和blockship的逐个得到结果
代码
代码也在这里
注意:只能使用C++>=11的编译器才能通过编译。(我提交时用的是 C++14 (GCC 5.4.1) 编译器)
#include <cstdio>
#include <vector>
#include <queue>
#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;
}