#include<cstdio>
#include<vector>
using namespace std;
const int N = 100010, K = 18;
int par[N][K]; // par[v][k] = parent at level 2^k above v
int cycle[N]; // cycle[i] = count of the #cycle in which edge i ---> par[i][0] is used
int sz[N]; // sz[i] = size of the component whose root is i
int dsuPar[N]; // dsuPar[i] = parent in dsu
int h[N]; // h[i] = dis(i, root) where {i, root} are in same component
vector<int> G[N];
void dfs_cycle(int v, int p = -1)
{
for(int u : G[v])
if(u != p)
{
dfs_cycle(u, v);
cycle[v] += cycle[u];
}
}
int root(int v)
{
if(dsuPar[v] == 0) return v;
return dsuPar[v] = root(dsuPar[v]);
}
int lca(int a, int b)
{
if(h[b] > h[a])
swap(a, b);
for(int i = 0; i < K; i++)
if((1<<i) & (h[a] - h[b]))
a = par[a][i];
if(a == b)
return a;
for(int i = K-1; i >= 0; i--)
if(par[a][i] != par[b][i])
a = par[a][i], b = par[b][i];
return par[a][0];
}
void dfs_reverse_cycle(int v, int p)
{
h[v] = h[p] + 1;
par[v][0] = p;
for(int k = 1; k < K; k++)
par[v][k] = par[par[v][k-1]][k-1];
for(int u : G[v])
if(u != p)
{
cycle[v] -= cycle[u];
dfs_reverse_cycle(u, v);
}
}
void merge(int u, int v)
{
int ru = root(u), rv = root(v);
if(rv == ru)
{
cycle[v]++;
cycle[u]++;
cycle[lca(u, v)] -= 2;
return;
}
if(sz[ru] > sz[rv])
swap(ru, rv), swap(u, v);
// ru have on the smaller size of component
dfs_cycle(ru); // find the cycle values of ru component
// update the path of a -> par[a][0] -> par[par[a][0]][0] -> .... -> ru
vector<int> path = {u};
while(par[path.back()][0]!=0)
path.push_back(par[path.back()][0]);
for(int i = path.size() - 1; i > 0; i--)
cycle[path[i]] = cycle[path[i-1]];
cycle[path[0]] = 0;
dfs_reverse_cycle(u, v);
G[u].push_back(v);
G[v].push_back(u);
dsuPar[ru] = rv;
sz[rv] += sz[ru];
}
int main()
{
int n, m;
scanf("%d %d",&n, &m);
for(int i = 1; i <= n; i++)
sz[i] = 1;
for(int i = 0; i < m; i++)
{
int u, v;
scanf("%d %d", &u, &v);
merge(u, v);
}
for(int i = 1; i <= n; i++)
if(par[i][0]==0)
dfs_cycle(i);
for(int i = 1; i <= n; i++)
if(cycle[i] == 0 and par[i][0]!=0)
printf("%d %d\n", i, par[i][0]);
return 0;
}
Compilation message
pipes.cpp: In function 'int main()':
pipes.cpp:102:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
102 | scanf("%d %d",&n, &m);
| ~~~~~^~~~~~~~~~~~~~~~
pipes.cpp:110:12: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
110 | scanf("%d %d", &u, &v);
| ~~~~~^~~~~~~~~~~~~~~~~
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
2 ms |
5468 KB |
Output is correct |
2 |
Correct |
1 ms |
5468 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
5564 KB |
Output is correct |
2 |
Correct |
7 ms |
5724 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
148 ms |
8584 KB |
Output is correct |
2 |
Correct |
145 ms |
8532 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
258 ms |
10964 KB |
Output is correct |
2 |
Correct |
291 ms |
11604 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
422 ms |
14932 KB |
Output is correct |
2 |
Correct |
361 ms |
14416 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Runtime error |
601 ms |
21840 KB |
Memory limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Runtime error |
937 ms |
29392 KB |
Memory limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Runtime error |
1228 ms |
36916 KB |
Memory limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Runtime error |
1553 ms |
42620 KB |
Memory limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Runtime error |
1969 ms |
48704 KB |
Memory limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |