codeforces 589H DFS

【題目鏈接】
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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章