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;
}
};