CF 589 H Tourist Guide

题目大意:
给一张无向图和一堆关键点,配对尽量多的点对使得不同点对路径不交(路径自定)。
题解:随便弄一棵森林做匹配即可。

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define N 100010
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct edges{
	int to,pre;
}e[N];int vis[N],fa[N],h[N],etop,anscnt,rt[N],lst1[N],lst2[N];
vector<int> zz[N],g[N];pair<pii,int> ans[N];
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
int dfs(int x) { vis[x]=1;int y;Rep(i,g[x]) if(!vis[y=g[x][i]]) add_edge(x,y),dfs(y);return 0; }
int solve(int x)
{
	for(int i=h[x],y;i;i=e[i].pre)
	{
		y=e[i].to,fa[y]=x,solve(y);
		Rep(j,zz[y]) zz[x].pb(zz[y][j]);
	}
	int n=(int)zz[x].size();if(n<=1) return 0;
	for(int i=0;i+1<=n-1;i+=2)
		ans[++anscnt]=mp(mp(zz[x][i],zz[x][i+1]),x);
	int y=zz[x][n-1];zz[x].clear();
	if(n&1) zz[x].pb(y);return 0;
}
int main()
{
	int n=inn(),m=inn(),k=inn(),cnt=0,x,y;
	rep(i,1,m) x=inn(),y=inn(),g[x].pb(y),g[y].pb(x);
	rep(i,1,k) x=inn(),zz[x].pb(x);
	rep(i,1,n) if(!vis[i]) rt[++cnt]=i,dfs(i);
	rep(i,1,cnt) solve(rt[i]);
	printf("%d\n",anscnt);
	rep(i,1,anscnt)
	{
		int x=ans[i].fir.fir,y=ans[i].fir.sec,c=ans[i].sec,l1=0,l2=0;
		while(x^c) lst1[++l1]=x,x=fa[x];while(y^c) lst2[++l2]=y,y=fa[y];
		printf("%d",l1+l2),lst1[++l1]=c;
		rep(j,1,l1) printf(" %d",lst1[j]);
		for(int j=l2;j;j--) printf(" %d",lst2[j]);
		printf("\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/83542425
今日推荐