AC链接
题目大意:给定一个 n 个节点, m 条边的图。如果某两条边有公共顶点,则这两条边可以匹配。问是否存在一个匹配方案,使得所有的边都恰好被匹配一次。
数据范围: 3≤n≤20000,2≤m≤100000, 其中 m 为偶数,且图联通。
跪膜大神fanhqme
膜拜链接
然而感觉就是xjbdfs…
在dfs搜索树上分治?(如果一定要强行加上什么算法的话…
在dfs到 u 的时候,分以下几种情况:
1.邻接点 v 的dfs树匹配满了,并返回-1。
2.单出来了一个节点 v ,返回 v ,与 u 的父亲的某一个点进行匹配。
对于已经访问的节点v按第二种情况处理。
(然而感觉并木有说清楚的样子…
然而POJ上根本就木有输出“No“的数据,感觉是一定有解?!
#include
#include
#define MAXM 100005
#define MAXN 20005
using namespace std;
struct node{int v, next;}edge[MAXM<<1];
int adj[MAXN], dfn[MAXN], tot, idx, out[MAXM][3], cnt;
inline void add(int u,int v){edge[++tot].v=v, edge[tot].next=adj[u], adj[u]=tot;}
int dfs(int u)
{
int ans=-1;
dfn[u]=++idx;
for(int p=adj[u], v, t;p;p=edge[p].next)
if(!dfn[v=edge[p].v])
{
t=dfs(v);
if(t==-1)
{
if(~ans)out[++cnt][0]=ans, out[cnt][1]=u, out[cnt][2]=v, ans=-1;
else ans=v;
}
else out[++cnt][0]=u, out[cnt][1]=v, out[cnt][2]=t;
}
else if(dfn[v]>dfn[u])
{
if(ans==-1)ans=v;
else out[++cnt][0]=ans, out[cnt][1]=u, out[cnt][2]=v, ans=-1;
}
return ans;
}
int main()
{
int n, m, u, v;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
{
scanf("%d%d",&u,&v);
add(u,v), add(v,u);
}
dfs(1);
if(cnt)for(int i=1;i<=cnt;++i)printf("%d %d %d\n",out[i][0],out[i][1],out[i][2]);
else puts("No");
return 0;
}