链接找不到了
发现如果对于一个联通块内的偶数个点,一定可以两两配对且不相交
如果相交,则调换组合顺序一定可以不相交
而如果我们把所有这些路径拿出来,边数一定小于等于联通块大小-1
所以直接在任意生成树上做就好
那么就dfs一下,判断一下有没有奇数个点就好了
dfs过程中,一个点的子树中的点最多向上传一个未匹配的点,剩下的直接构造
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=50005,M=50005;
int n,m,k;
int vis[N<<1],nxt[N<<1],head[N<<1],tot=0;
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
int spi[N],pt[N],dep[N],fa[N],ans;
vector<int>vec[N];
inline void adde(int u,int v){add(u,v);add(v,u);}
void add_path(int a,int b,int lca){
++ans;
int len=dep[a]+dep[b]-2*dep[lca];
vec[ans]=vector<int>(len+1,0);
int p;
for(p=0;a!=lca;p++,a=fa[a]) vec[ans][p]=a;
vec[ans][p]=lca;
for(p=len;b!=lca;p--,b=fa[b]) vec[ans][p]=b;
}
int dfs(int v,int f){
pt[v]=true;fa[v]=f;dep[v]=dep[f]+1;
int a=spi[v]?v:0,b;
for(int i=head[v];i;i=nxt[i]){
int y=vis[i];
if(y==f || pt[y]) continue;
b=dfs(y,v);
if(b){
if(a) add_path(a,b,v),a=0;
else a=b;
}
}
return a;
}
int main(){
n=read();m=read();k=read();
for(int x,y,i=1;i<=m;i++){x=read();y=read();adde(x,y);}
for(int i=1;i<=k;i++){int x=read();spi[x]=1;}
for(int i=1;i<=n;i++) if(!pt[i]) dfs(i,0);
cout<<ans<<"\n";
for(int i=1;i<=ans;i++){
int L=vec[i].size();
cout<<L-1<<" ";
for(int j=0;j<L;j++) cout<<vec[i][j]<<" ";
cout<<"\n";
}
return 0;
}