1098: [POI2007] office building Biu Time limit:20 Sec Memory limit:162 MB
submit:1204 solved:558
[Submit] [Status] [Discuss] Description
FGD opened a telephone company. He hired n clerks and gave each clerk a cell phone. Every employee's cell phone is stored with a few colleagues.
Phone number. As FGD's company expands, the old office building has become so narrow that FGD decided to relocate the company to some new offices. FG
D want staff to be housed in as many office buildings as possible, which will have a relatively better working environment for every employee. However, in order to
For convenience, if two employees are housed in two different office buildings, they must have each other's telephone number. Input
The first row contains two integers N (2<=n<=100000) and M (1<=m<=2000000). The clerk is numbered sequentially 1,2,......, N. The following M line, each
Row contains two positive numbers a and B (1<=a Output
contains two lines. The first line contains a number s, which indicates the number of office buildings that the FGD can place in the staff. The second line contains s from a small to large array
Number, each number followed by a space, indicating the number of employees arranged in each office. Sample Input 7 16
1 3
1 4
1 5
2 3
3 4
4 5
4 7
4 6
5 6
6 7
2 4
2 7
2 5
3 5
6 R
1 7
Sample Output 3
1 2 4 HINT
FGD can arrange staff 4 into an office building, staff 5 and staff 7 arranged into the 2nd office Building, the others into the Office Building No. 3rd.
Source
[Submit] [Status] [Discuss]
Solving: Complement graph + link list optimizes BFS.
Yesterday looked up some things about the complement, and then see this problem is actually to find the number of connected components of the complement graph.
The so-called complement map, is to delete the existing side, no side plus. The two points in the complement are the people who don't have the phone number, so they must be in an office building.
But this problem has a lot of points, but the original image of the edge is very small. Therefore, we can not build the complement graph, we need to find the size and number of the connected components of the complement graph on the basis of the original image.
We consider a point where there is a point that needs to be connected to him in a connected component, and then we can tag the dots that are connected to him, each time we find unmarked and unassigned points to join the queue, update the answers and expand them. Note that each time you finish, you need to clear the attached tag, because the current point of the relationship can make two people do not work in the same building, but the points in the new queue may need these points in the same building office.
This still cannot be solved in the time of science. Then there is the list optimization bfs. Because each point can only belong to a building, then we use the linked list to maintain the remaining unassigned points, if we assign a point to the office building, it is deleted from the list, effectively reducing the number of times each point is enumerated.
Time complexity O (n+m)
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <
cmath> #include <queue> #define N 4000003 using namespace std;
int Vis[n],n,m,num[n],ans;
int point[n],next[n],v[n],tot,l[n],r[n],mark[n];
void Add (int x,int y) {tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; tot++; Next[tot]=point[y]; Point[y]=tot;
V[tot]=x;
cout<<x<< "" <<y<<endl;}
void del (int x) {vis[x]=1;
R[L[X]]=R[X];
L[R[X]]=L[X];
} void BFs (int x) {queue<int> p; p.push (x);
while (!p.empty ()) {int Now=p.front (); P.pop ();
num[ans]++;
for (int i=point[now];i;i=next[i]) mark[v[i]]=1;
for (int i=r[0];i;i=r[i]) if (!vis[i]&&!mark[i]) del (i), P.push (i);
for (int i=point[now];i;i=next[i]) mark[v[i]]=0;
int main () {freopen ("a.in", "R", stdin);
scanf ("%d%d", &n,&m);
for (int i=1;i<=m;i++) {int x,y; scanf ("%d%d", &x,&y);
Add (x,y); for (int i=0;i<=n;i++) l[i]=i-1,r[i]=i+1;
r[n]=0;
for (int i=1;i<=n;i++) if (!vis[i]) {ans++;
Del (i);
BFS (i);
Sort (num+1,num+ans+1);
printf ("%d\n", ans);
for (int i=1;i<=ans;i++) printf ("%d", num[i]);
printf ("\ n"); }