一、实现并查集的简洁写法
int lead(int x)//
{
if(leader[x]==x) return x;
else return leader[x]=lead(leader[x]); //把路径上所有点都纠正
}
int link(int x,int y)
{
if(leader[x]!=leader[y])
{
leader[lead(x)]=lead(y);
}
}
leader[]表示直属上级
link()实现了两个互不相关组的连接,把x的root一起并入y的子结点中
note:return leader[x]=lead(leader[x])要用递归的思想去理解,先改变上级与root的link再递归回来改变自己。
二、关于一些DFS和DP的使用
Despite the fact that DFS has certain templates,we should not let them limit our thoughts,because we create DFS,(it is easy now to find people using DFS but it gets much harder to find a skilled DFS master.)Below are some examples.(haha,just a English Beginner trying to write something)
question1:
戳我跳转
对于dfs,经常使用递归方式实现,正向有时候很好用
从上往下依次推出金字塔各个位置上的最大值,最后比较
#include<cstdio>
int n,a[1002],i,j,ans,p;
int max(int &x,int &y){return x>y?x:y;}
int main(){
scanf("%d",&n);
for(i=n;i;i--)
for(j=i;j<=n;j++)
scanf("%d",&p),a[j]=max(a[j],a[j+1])+p;
for(i=1;i<=n;i++)
ans=max(ans,a[i]);
printf("%d",ans);
return 0;
}
question2:关于多参数DFS的使用
戳我跳转
DFS在于实现层层递归,因此需要把重要参数层层传递。
下面这道题在进行层层深入时使用了
stp:走的步数 (用于还原路径)
sum:挖矿总数
x:要走的位置
#include<iostream>
#include<cstdio>
using namespace std;
bool v[30];//是否访问过
int bomb[30];//地雷数目
int path[30],ans[30],cnt;//path记录路径
int ac[30][30];//查看是否有通路
int n;
int maxx;//记录最大地雷数目
bool check(int x)
{
for(int i=1;i<=n;i++){
if(ac[x][i]&&!v[i]) return false;
}
}
int dfs(int x,int stp,int sum)//走步数
{
if(check(x))
{
if(maxx<sum)
{
maxx=sum;
cnt=stp;
for(int i=1;i<=stp;i++){
ans[i]=path[i];
}
}
}
for(int i=1;i<=n;i++){
if(ac[x][i]&&!v[i]){
v[i]=1;//标记走过
path[stp+1]=i;//记录路径
dfs(i,stp+1,sum+bomb[i]);
v[i]=0;
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>bomb[i];
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
cin>>ac[i][j];
for(int i=1;i<=n;i++){
v[i]=1;
path[1]=i;
dfs(i,1,bomb[i]);
v[i]=0;
}
for(int i=1;i<=n;i++){
v[i]=1;
path[1]=i;
dfs(i,1,bomb[i]);
v[i]=0;
}
for(int i=1;i<=cnt;i++)
cout<<ans[i]<<' ';
cout<<endl<<maxx;
return 0;
}
question3:记忆化方法实现
#include<iostream>
using namespace std;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int n,m,a[201][201],s[201][201],ans;
bool use[201][201];
int dfs(int x,int y)
{
if(s[x][y]) return s[x][y];
s[x][y]=1;
for(int i=0;i<4;i++){
int xx=dx[i]+x;
int yy=dy[i]+y;
if(xx>0&&yy>0&&xx<=n&&yy<=m&&a[x][y]>a[xx][yy]){
dfs(xx,yy);
s[x][y]=max(s[x][y],s[xx][yy]+1);
}
}
return s[x][y];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans=max(ans,dfs(i,j));
cout<<ans;
return 0;
}
实现了每走一条路标记一条路。有点最优子结构的dp的意思了