传送门
貌似跟图没啥关系啊。。。
随便找出一种生成森林出来,可以通过归纳法证明任意一棵子树最多有一个特殊点没有被匹配。
然后就做完啦。
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return *ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
typedef pair<int,int> pii;
const int N=50005;
int n,m,k,dep[N],siz[N],fa[N],top[N],hson[N];
vector<int>e[N],g[N];
vector<pii>ans;
bool exi[N],vis[N];
int dfs1(int p){
vis[p]=1,hson[p]=0,siz[p]=1;
vector<int>ss;
if(exi[p])ss.push_back(p);
for(ri t,i=0,v;i<e[p].size();++i){
if(vis[v=e[p][i]])continue;
g[p].push_back(v);
fa[v]=p,dep[v]=dep[p]+1,t=dfs1(v),siz[p]+=siz[v];
if(t)ss.push_back(t);
if(siz[v]>siz[hson[p]])hson[p]=v;
}
int a,b;
while(ss.size()>1){
a=ss.back();
ss.pop_back();
b=ss.back();
ss.pop_back();
ans.push_back(pii(a,b));
}
return ss.size()?ss.back():0;
}
void dfs2(int p,int tp){
top[p]=tp;
if(!hson[p])return;
dfs2(hson[p],tp);
for(ri i=0,v;i<g[p].size();++i)if((v=g[p][i])^hson[p])dfs2(v,v);
}
inline int lca(int x,int y){
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
inline void print(int x,int y){
int t=lca(x,y);
cout<<dep[x]+dep[y]-2*dep[t]<<' ';
vector<int>res;
while(1){
res.push_back(x);
if(x==t)break;
x=fa[x];
}
for(ri i=0,up=res.size();i<up;++i)cout<<res[i]<<' ';
res.clear();
while(y!=t){
res.push_back(y);
y=fa[y];
}
reverse(res.begin(),res.end());
for(ri i=0,up=res.size();i<up;++i)cout<<res[i]<<' ';
puts("");
}
int main(){
n=read(),m=read(),k=read();
for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
for(ri i=1;i<=k;++i)exi[read()]=1;
for(ri i=1;i<=n;++i)if(!vis[i])dfs1(i),dfs2(i,i);
cout<<ans.size()<<'\n';
for(ri i=0;i<ans.size();++i)print(ans[i].fi,ans[i].se);
return 0;
}