//#define LOCAL#include<bits/stdc++.h>usingnamespace std;#define ll long long#define mem(a, b) memset(a,b,sizeof(a))#define sz(a) (int)a.size()#define INF 0x3f3f3f3f#define DNF 0x7f#define DBG printf("this is a input\n")#define fi first#define se second#define mk(a, b) make_pair(a,b)#define pb push_back#define LF putchar('\n')#define SP putchar(' ')#define p_queue priority_queue#define CLOSE ios::sync_with_stdio(0); cin.tie(0)#define sz(a) (int)a.size()#define pii pair <int,int>template<typename T>voidread(T &x){x =0;char ch =getchar();ll f =1;while(!isdigit(ch)){if(ch =='-')f *=-1;ch =getchar();}while(isdigit(ch)){x = x *10+ ch -48; ch =getchar();}x *= f;}template<typename T,typename... Args>voidread(T &first, Args&... args){read(first);read(args...);}template<typename T>voidwrite(T arg){T x = arg;if(x <0){putchar('-'); x =- x;}if(x >9){write(x /10);}putchar(x %10+'0');}template<typename T,typename... Ts>voidwrite(T arg, Ts ... args){write(arg);if(sizeof...(args)!=0){putchar(' ');write(args ...);}}usingnamespace std;
ll gcd(ll a, ll b){return b ==0? a :gcd(b, a % b);}
ll lcm(ll a, ll b){return a /gcd(a, b)* b;}constint N =1e5+5;int T;int n , m , k, flag =1;
vector <int> edge[N];
queue <int> q;int vis[N], vis2[N], deg[N];
vector <int> ve;void solve (){while(!q.empty())
q.pop();for(int i =1; i <= n ; i ++)if(deg[i]< k)
q.push (i), vis[i]=1;while(!q.empty()){int u = q.front ();
q.pop ();
vis[u]=1;if(deg[u]== k-1){
ve.clear();
ve.pb (u);for(auto it : edge[u]){if(!vis2[it])
ve.pb(it);}int mark =1;for(int i =0; i < ve.size(); i ++){for(int j =0; j < ve.size(); j++){if(ve[i]== ve[j])break;if(!binary_search(edge[ve[i]].begin(),edge[ve[i]].end(),ve[j]))
mark =0;}}if(mark){
flag =0;break;}
ve.clear();}
vis2[u]=1;for(auto it : edge[u]){
deg[it]--;if(deg[it]< k &&!vis[it]){
q.push(it), vis[it]=1;}}}}intmain(){
CLOSE;
cin >> T;while(T --){
flag =1;
cin >> n >> m >> k;for(int i =1; i <= m ; i ++){int u , v;
cin >> u >> v;
edge[u].pb (v);
edge[v].pb (u);}for(int i =1; i <= n ; i ++)
sort (edge[i].begin(), edge[i].end()), deg[i]=sz(edge[i]);
solve ();if(!flag){
cout <<2<< endl;for(auto it : ve)
cout << it <<' ';
cout << endl;}else{
set <int> s;for(int i =1; i <= n ; i ++){for(auto it : edge[i])if(!vis[it])
s.insert (it);}if(sz(s)==0)
cout <<-1<< endl;else{
cout <<1<<' '<< sz (s)<< endl;for(auto it : s)
cout << it <<' ';
cout << endl;}}for(int i =1; i <= n ; i ++)
edge[i].clear(), deg[i]= vis[i]= vis2[i]=0;}}
解题思路:没有什么好的想法,看见
K
K
K的值比较小,就想到了全排列枚举,然后去
O
(
N
)
O(N)
O(N)判断环,然后就没了。看题解之后发现,完全可以
H
a
s
h
Hash
Hash一下,处理出每个度的第
i
i
i大的边可到达的集合,然后枚举全排列后检查一下是否能够到达
N
N
N个点就好
constint N =2e5+5;int n ,m ,k;int deg[N], ans =0;int val[N], flag =0, p[15][15];
vector <pii> edge[N];int tmp[15];void dfs (int now){if(now > k){int mark =0;for(int i =1; i <= k ; i ++)
mark += p[i][tmp[i]];if(mark == flag)
ans ++;return;}for(int i =1; i <= now ; i ++)
tmp[now]= i, dfs (now +1);}intmain(void){
CLOSE;srand(time(0));
cin >> n >> m >> k;for(int i =1; i <= n ; i ++)
val[i]= rand (), flag += val[i];for(int i =1; i <= m ; i ++){int u, v, w;
cin >> u >> v >> w;
deg[u]++;
edge[u].pb(mk(w,v));}for(int i =1; i <= n ; i ++)
sort (edge[i].begin(), edge[i].end());for(int i =1; i <= n ; i ++){for(int j =0; j < edge[i].size(); j ++){
p[deg[i]][j+1]+= val[edge[i][j].se];}}
dfs (1);
cout << ans << endl;}
constint N =5e5+5;int T;int n , m;
vector <int> edge[N];int dep[N], fa[N], maxn, vis[N];
vector <int> node[N];void dfs (int u ,int pa){for(auto v : edge[u]){if(v != pa &&!dep[v]){
fa[v]= u;
dep[v]= dep[u]+1;
node[dep[v]].pb(v);
maxn = max (maxn, dep[v]);
dfs (v, u);}}}intmain(void){
CLOSE;
cin >> T;while(T --){
maxn =0;
cin >> n >> m;for(int i =1; i <= m ; i ++){int u , v;
cin >> u >> v;
edge[u].pb (v);
edge[v].pb (u);}
vector <int> ve;int ok =1;
dep[1]=1;
dfs (1,1);for(int i =1; i <= n ; i ++){if(dep[i]>=(n +1)/2){
ok =0;
cout <<"PATH"<< endl;
cout << dep[i]<< endl;int x = i;
ve.pb (x);while(fa[x])
ve.pb(fa[x]), x = fa[x];break;}}if(!ok){for(auto v : ve)
cout << v <<' ';
cout << endl;for(int i =0; i <= n ; i ++)
edge[i].clear(), node[i].clear(), dep[i]= vis[i]= fa[i]=0;continue;}for(int i =0; i <= maxn ; i +=2){for(auto v : node[i])
vis[v]=1;}
cout <<"PAIRING"<< endl;
vector <int> ans;int len =0;for(int i =1; i <= maxn ; i ++)
len +=(sz(node[i])/2);
cout << len << endl;for(int i =1; i <= maxn ; i ++)for(int j =0; j <sz(node[i])-1; j +=2)
cout << node[i][j]<<' '<< node[i][j+1]<< endl;for(int i =1; i <= n ; i ++)
edge[i].clear(), node[i].clear(), dep[i]= vis[i]=0;}}
解题思路:搞出一颗搜索树之后,然后利用非树边找一下环就好了。如果存在
L
e
n
(
c
y
c
l
e
)
<
=
k
Len(cycle) <= k
Len(cycle)<=k 直接输出,如果不存在找一个
L
e
n
(
c
y
c
l
e
)
>
k
Len(cycle) > k
Len(cycle)>k 的环输出一半,如果不存在环直接二分图染色就行
constint N =5e5+5;int T;int n , m , k;struct node {int f, t, next, mark;}edge[N];int head[N], cnt, fa[N];void add (int f,int t){
edge[cnt].mark =0;
edge[cnt].f = f;
edge[cnt].t = t;
edge[cnt].next = head[f];
head[f]= cnt ++;}//LCA部分int bz[N][30], deep[N];voiddfs(int rt,int dep){
deep[rt]= dep;for(int i = head[rt]; i !=-1; i = edge[i].next){int v = edge[i].t;if(!deep[v]){
fa[v]= rt;
edge[i].mark = edge[i^1].mark =1;
bz[v][0]= rt;dfs(v,dep +1);}}}voiddeal(){for(int i =1; i <=25; i ++)for(int j =1; j <= n ; j ++)
bz[j][i]= bz[bz[j][i-1]][i-1];}intLCA(int x,int y){if(deep[x]< deep[y])swap(x,y);int t = deep[x]- deep[y];for(int i =0;(1<<i)<= t ; i ++)if((1<<i)&t)x=bz[x][i];for(int i=19; i >=0; i--)if(bz[x][i]^ bz[y][i])
x=bz[x][i], y=bz[y][i];if(x==y)return x;return bz[x][0];}
vector <int> ve;int ok =0, ok2 =0;void solve (){for(int i =0; i < cnt ; i +=2){if(!edge[i].mark){int u = edge[i].f , v = edge[i].t;int lca = LCA (u, v);int len = deep[u]+ deep[v]-2* deep[lca]+1;if(len <= k){
cout <<2<< endl;if(deep[u]> deep[v])
swap (u, v);if(u == lca){while(v != lca){
ve.pb (v);
v = fa[v];}
ve.pb (lca);}else{while(u != lca){
ve.pb(u);
u = fa[u];}while(v != lca){
ve.pb(v);
v = fa[v];}
ve.pb(lca);}
cout <<sz(ve)<< endl;for(auto it : ve)
cout << it <<' ';
cout << endl;
ok =1;return;}}}}intmain(){
CLOSE;
mem (head,-1);
cin >> n >> m >> k;for(int i =1; i <= m ; i ++){int u , v;
cin >> u >> v;
add (u, v);
add (v, u);}
dfs (1,1);
deal ();
solve ();if(ok)return0;for(int i =0; i < cnt ; i +=2){if(!edge[i].mark){int u = edge[i].f , v = edge[i].t;int lca = LCA (u, v);int len = deep[u]+ deep[v]-2* deep[lca]+1;if(len > k){
ok2 =1;
cout <<1<< endl;if(deep[u]> deep[v])
swap (u, v);if(u == lca){while(v != lca){
ve.pb (v);
v = fa[v];}
ve.pb (lca);}else{while(u != lca){
ve.pb(u);
u = fa[u];}
vector <int> ve2;
ve.pb(lca);while(v != lca){
ve.pb(v);
v = fa[v];}reverse(ve2.begin(),ve2.end());for(auto it : ve2)
ve.pb(it);}int cur =0;for(int j =1; j <=(k+1)/2; j ++)
cout << ve[cur]<<' ', cur +=2;return0;}}}if(ok2)return0;int tot =0;for(int i =1; i <= n ; i ++)if(deep[i]%2)
tot ++;int p =0;
cout <<1<< endl;if(tot >=(k+1)/2){for(int i =1; i <= n ; i ++)if(deep[i]%2){
cout << i <<' ';
p +=1;if(p ==(k+1)/2)break;}}else{for(int i =1; i <= n ; i ++)if(deep[i]%2==0){
cout << i <<' ';
p +=1;if(p ==(k+1)/2)break;}}
cout << endl;}
解题思路:看完题之后,会发现本题存在一个先后顺序,如果没有特殊限制,那么直接建图之后拓扑排序就好了,但是现在有特殊条件,那么我们只需要强制把特殊条件的点捆绑在一起,这个地方我们利用并查集就好了,注意,这里的并查集以
X
X
X为根,输出的时候
d
f
s
dfs
dfs一下就好了
constint N =3e5+5;int n , k, deg[N], Deg[N];
vector <int> edge[N],E[N], ans,Edge[N];
queue <int> q;
vector <pii> ip;int fa[N], tot;
map <pii,int> ma;int findroot (int x){if(fa[x]== x)return x;return fa[x]= findroot (fa[x]);}bool merge (int x,int y){int fax = findroot (x);int fay = findroot (y);if(fax != fay){
fa[fay]= fax;returntrue;}returnfalse;}voidtopo(){for(int i =1; i <= n ; i ++){if(!deg[i]&& i == findroot (i))
q.push(i), ans.pb(i);}while(!q.empty()){int u = q.front();
q.pop();for(auto v : edge[u]){
deg[v]--;if(!deg[v])
q.push(v), ans.pb(v);}}}bool topo2 (){for(int i =1; i <= n ; i ++)if(!Deg[i])
q.push(i);while(!q.empty()){int u = q.front();
q.pop();for(auto v : Edge[u]){
Deg[v]--;if(!Deg[v])
q.push(v);}}for(int i =1; i <= n ; i ++)if(Deg[i])returntrue;returnfalse;}void dfs (int x){
cout << x <<' ';for(auto v : E[x])
dfs (v);}int main (void){
CLOSE;int ok =1;
cin >> n >> k;for(int i =1; i <= n ; i ++)
fa[i]= i;for(int i =1; i <= n ; i ++){int x;
cin >> x;if(x ==0)continue;
ip.pb(mk(x,i));
Edge[x].pb(i);
Deg[i]++;}while(k --){int u , v;
cin >> u >> v;
Edge[u].pb(v);
Deg[v]++;
E[u].pb(v);
merge (u, v);}if(topo2()){
cout <<0<< endl;return0;}int sz =0;for(int i =1; i <= n ; i ++)if(findroot (i)== i)
sz ++;for(auto it : ip){int u = findroot (it.fi);int v = findroot (it.se);if(u != v){
edge[u].pb(v);
deg[v]++;}}topo();if(sz(ans)== sz)for(auto v : ans)
dfs (v);else
cout <<0;
cout << endl;}