Codeforces Round #663 (Div. 2)
E Pairs of Pairs
题意:给一个联通图,求以下两种答案任意一种:
- 求一条长度至少为⌈ n 2 \frac{n}{2} 2n⌉的路径。
- 求至少⌈
n
2
\frac{n}{2}
2n⌉个点,这些点两两构成一对,每两对点构成的集合中最多只有两条边。
思路:建图的dfs树,如果树深大于⌈ n 2 \frac{n}{2} 2n⌉,输出路径。否则,将树分层,深度相同的节点之间配对,这样可以保证任意两对节点构成的集合中有不超过2条边;同时,由于每一层最多会有一个点无法配对,所以无法配对的点小于⌈ n 2 \frac{n}{2} 2n⌉,因此可以满足要求。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int N = 5e5 + 10;
const int M = 1e6 + 10;
struct EDGE{
int to, nxt;
}edge[M * 2];
int t[N], fa[N], dep[N], vist[N];
vector<int>vec[N];
int tot;
void myclear(int n)
{
for(int i = 1;i <= n; i++)
{
vec[i].clear();
fa[i] = 0;
t[i] = 0;
vist[i] = 0;
}
tot = 0;
}
void addedge(int x, int y)
{
edge[++tot].nxt = t[x];
edge[tot].to = y;
t[x] = tot;
}
void dfs(int x)
{
vist[x] = 1;
for(int p = t[x]; p; p = edge[p].nxt)
{
int y = edge[p].to;
if(y != fa[x] && !vist[y])
{
fa[y] = x;
dep[y] = dep[x] + 1;
dfs(y);
}
}
}
void solve(int n)
{
for(int i = 1;i <= n; i++)
if(dep[i] >= (n + 1) / 2)
{
printf("PATH\n");
printf("%d\n",dep[i]);
while(i)
{
printf("%d ",i);
i = fa[i];
}
printf("\n");
return;
}
for(int i = 1; i <= n; i++)
vec[dep[i]].push_back(i);
int cnt = 0;
for(int i = 1;i <= n; i++)
cnt += vec[i].size() / 2;
printf("PAIRING\n");
printf("%d\n", cnt);
for(int i = 1;i <= n; i++)
if(vec[i].size() >= 2)
for(int j = 0; j + 1 < vec[i].size(); j += 2)
printf("%d %d\n", vec[i][j], vec[i][j + 1]);
}
int main()
{
int T;
scanf("%d", &T);
while(T)
{
T--;
int n, m, x, y;
scanf("%d%d", &n, &m);
myclear(n);
for(int i = 1; i <= m; i++)
{
scanf("%d%d", &x, &y);
addedge(x, y);
addedge(y, x);
}
dep[1] = 1;
dfs(1);
solve(n);
}
return 0;
}