codeforces 589H DFS

来源:互联网 发布:三级域名申请 编辑:程序博客网 时间:2024/05/15 23:46

【题目链接】
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=106786#problem/D

【解题报告】
给定n个点和m条边的无向连通图,和k个特殊点,任意两个特殊点之间连一条路,任意一个特殊点不能是两条路的端点。问最多能连多少条路。
这个题目我是不会的(图论思维真的很弱。。。)。
这个题还是重点要学习怎么分析题目的。

对于一个连通块,我们通过深搜把它变成树,如果它内部有2i个匹配点,则两两匹配。如果有2i+1个匹配点,那么就出现一个不能匹配的点,它需要上溯和他的父节点或者兄弟子树中的节点来匹配。依据此来进行DFS搜索。
一个连通块里如果有k个特殊点,那么一定存在k/2条路。注意题目没有说明给出的图是联通图,所以数据可能是多个联通块,处理的时候还需要维护一下路径总数。

寻找路径的方法是DFS。因为没有写过这类题,不太清楚这种把图当作树处理的代码的实现细节。所以学习了一下别人的代码。
http://blog.csdn.net/playwfun/article/details/49618017

这里面对容器使用了泛型迭代器.for+auto指遍历这个容器的所有元素。需要学习使用这种迭代器(比iterator简洁)

【参考代码】

#include<bits/stdc++.h>using namespace std;const int maxn=5e5+100;int pa[maxn],dep[maxn],link[maxn];bool mark[maxn],vis[maxn];vector<int>G[maxn];int n,m,k;int ans=0;int dfs( int u, int fa ){      vis[u]=1; pa[u]=fa;      dep[u]=(fa==-1 ? 0 : dep[fa] )+1;      int now=mark[u]?u:-1;      for( auto v:G[u] )      {            if(vis[v])continue;            int It=dfs( v,u ); //返回一个子树内一个没有匹配的特殊点            if(It==-1)continue;            if(now==-1)now=It; //以特殊点为起点            else{                  link[now]=It;                  link[It]=now;                  now=-1;                  ans++;            }        }        return now;}void print(){      memset( vis,0,sizeof vis );      for( int i=1;i<=n;i++ )if( link[i] && !vis[i] )      {            vis[i]=vis[link[i]]=1;            int u=i,v=link[i];            vector<int>lt,rt;            lt.push_back(u);            rt.push_back(v);            int cnt_=0;            while( u!=v ){                  if(dep[u]<dep[v])rt.push_back(pa[v]),v=pa[v];                  else lt.push_back(pa[u]),u=pa[u];            }            for( int i=rt.size()-2;i>=0;i-- )lt.push_back( rt[i] );            cout<<lt.size()-1;            for( int i=0;i<lt.size();i++ )                  cout<<" "<<lt[i];            cout<<endl;      }}int main(){      cin>>n>>m>>k;      int x,y;      for( int i=1;i<=m;i++ )      {            int x,y;   cin>>x>>y;             G[x].push_back(y);             G[y].push_back(x);      }      for( int i=1;i<=k;i++ )      {            int x; cin>>x;            mark[x]=true;      }      for( int i=1;i<=n;i++ )if(!vis[i])dfs(i,-1);      cout<<ans<<endl;      print();      return 0;}
0 0