topcoder srm 682 div1 -3

1、给定一个$n$个节点的无向图。找到一个长度为4的链。$5\leq n \leq 2000$

思路:枚举链的起点,暴力搜索即可。因为假设图中最长链的长度是3,那么搜索的最大复杂度是$O(n^{2})$。

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <assert.h>
using namespace std;

const int N=2005;


vector<int > g[N];
int h[N];

int dfs(int u,int pre,int cnt)
{
    if(cnt==5) return 1;
    h[u]=1;
    for(int i=0;i<(int)g[u].size();++i)
    {
        int v=g[u][i];
        if(v!=pre&&!h[v]&&dfs(v,u,cnt+1))
            return 1;
    }
    h[u]=0;
    return 0;
}


class SmilesTheFriendshipUnicorn
{
public:
	string hasFriendshipChain(int n,vector<int> A,vector<int> B)
	{
	    const int m=(int)A.size();

	    for(int i=0;i<m;++i)
        {
            int u=A[i];
            int v=B[i];

            g[u].push_back(v);
            g[v].push_back(u);
        }
        for(int i=0;i<n;++i)
        {
            memset(h,0,sizeof(h));
            if(dfs(i,-1,1)) return "Yay!";
        }

        return ":(";
	}
};

2、给定一个$n$个点$n$条边的无向图。可以进行若干次更新,每次更新有三步:(1)选择两个相邻的点$x,y$;(2)将$x,y$合并成一个新的点$z$;(3)$x,y$之间的边消失,其余跟$x$或者$y$相连的边现在连到$z$上。现在进行最少次数的更新使得最后的图满足:存在一个点$u$使得对于图中任意两个点$x,y$,$x$到$y$ 的路径必经过$u$。$1\leq n \leq 50$

思路:最后图的样子一定是一个中心点,该中心点有若干个相邻的节点。$n$个点$n$条边,那么必存在一个环。首先找到这个环,将环上的边删掉后,就变成若干棵有根树(树根就是在环上的节点$c$)。对于每棵树,最后一定会被更新成$c$上连着几个节点的样子;那么最后就是将环进行更新。

这其中,需要根据环的大小跟每个树根上的情况进行分类讨论。

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <assert.h>
using namespace std;

const int N=55;

vector<pair<int,int> > g[N];
int n;

int low[N],dfn[N],id;
int h[N];
int fa[N];

int c0,c1;

void dfs(int u)
{
    low[u]=dfn[u]=++id;
    for(int i=0;i<(int)g[u].size();++i)
    {
        int id=g[u][i].second;
        if(!h[id])
        {
            h[id]=1;
            int v=g[u][i].first;
            if(!dfn[v])
            {
                dfs(v);
                fa[v]=u;
                low[u]=min(low[u],low[v]);
            }
            else
            {
                c0=u;
                c1=v;
                low[u]=min(low[u],dfn[v]);
            }
        }
    }
}

int d[N];
int inCircle[N];


int cost,nodeNum;

void DFS(int u,int pre)
{
    if(d[u]!=1) ++cost;
    for(int i=0;i<(int)g[u].size();++i)
    {
        int v=g[u][i].first;
        if(!inCircle[v]&&v!=pre) DFS(v,u);
    }
}

pair<int,int> get(int u)
{
    cost=0; nodeNum=0;
    for(int i=0;i<(int)g[u].size();++i)
    {
        int v=g[u][i].first;
        if(!inCircle[v])
        {
            DFS(v,u);
            ++nodeNum;
        }
    }
    return make_pair(cost,nodeNum);
}

class SuccessfulMerger
{
public:
	int minimumMergers(vector<int> road)
	{
	    n=(int)road.size();
	    if(n<=2) return 0;

	    for(int i=0;i<n;++i)
        {
            g[i].push_back(make_pair(road[i],i));
            g[road[i]].push_back(make_pair(i,i));
            ++d[i];
            ++d[road[i]];
        }


        dfs(0);

        vector<int> V;
        V.push_back(c0);
        while(c0!=c1)
        {
            c0=fa[c0];
            V.push_back(c0);
        }
        for(int i=0;i<(int)V.size();++i) inCircle[V[i]]=1;

        int ans=0,kk=0;
        for(int i=0;i<(int)V.size();++i)
        {
            pair<int,int> p=get(V[i]);
            ans+=p.first;
            if(p.second)  ++kk;
        }
        const int K=(int)V.size();
        if(kk==0) ans+=K-2;
        else if(kk==1) ans+=K-2;
        else if(kk==2)
        {
            if(K==2) ans+=1;
            else ans+=K-2;
        }
        else
        {
            if(kk==K) ans+=K-1;
            else ans+=K-2;
        }
        return ans;
	}
};

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值