文中沒給代碼的後期補上,有AC的同學歡迎評論發一下代碼
牛客討論帖 https://www.nowcoder.com/discuss/98663?type=2&order=0&pos=5&page=1
這道題考察的是並查集(或者DFS),看代碼前請先了解一下並查集
並查集解釋
上面那個鏈接的博客裏面代碼有點錯誤,錯誤之處在評論中有指出
並查集思路:
#include <stdio.h>
#define N 100020
int friends[N];//每個人所屬的連通分量,即構成朋友樹時每個人的父節點
int rank[N];//連通分量的權值,即朋友樹的大小
int res;
void init(int n)//初始化initialization
{
for(int i=0;i<n;i++)
{
friends[i]=i;
rank[i]=0;
}
}
int findRoot(int x)//尋找x所屬的朋友樹的根節點
{
//一直向上遍歷尋找根節點
while(x != friends[x])
x = friends[x];
return x;
}
void connect(int x,int y)
{
int xRoot = findRoot(x);
int yRoot = findRoot(y);
if(xRoot == yRoot)
return ;
//判斷樹高,小樹並在大樹下
if(rank[xRoot] < rank[yRoot])
friends[xRoot]=yRoot;
else
{
friends[yRoot] = xRoot;
if(rank[xRoot]==rank[yRoot])//兩樹高相等,合併後樹高+1
rank[xRoot]++;
}
--res;
}
int main()
{
int n;
init(N);//初始化
scanf("%d",&n);
res = n;
for(int i=1;i<=n;i++){
int t;
while(~scanf("%d",&t)){
if(t == 0)
break;
connect(i,t);
}
}
printf("%d",res);
/*
10
0
5 3 0
8 4 0
9 0
9 0
3 0
0
7 9 0
0
9 7 0
*/
return 0;
}
DFS思路:
#include <iostream>
#include <vector>
using namespace std;
int n;
int res;
void dfs(vector<vector<int>>& friends, int x, int y,vector<vector<bool>>& mark){
if(x >= friends.size() || y >= friends[0].size() || x < 0 || y < 0)
return;
if(mark[x][y] == true)
return;
if(friends[x][y] == 0){
mark[x][y] = true;
return;
}
// 對於已經搜索過的點要進行標記
mark[x][y] = true;
res--;
for(int j=1; j<n; j++){
dfs(friends, x, j, mark);
}
}
void minM(vector<vector<int>>& friends) {
if(friends.empty())
return;
res = n;
vector<vector<bool>> vecMark(friends.size(),vector<bool>(friends[0].size(),false));// 定義標記數組
//開始搜索
for(int i = 1;i < friends.size();i++){
for(int j = 1;j < friends[0].size();j++){
if(vecMark[i][j] == true)
continue;
if(friends[i][j] == 0){
vecMark[i][j] = true;
continue;
}
dfs(friends, i, j, vecMark);
}
}
cout << num << endl;
}
int main()
{
cin >> n;
vector<vector<int>> friends(n+1, vector<int>(n+1,0));
int temp = 0;
for(int i=1; i<=n; i++){
int j = 1;
while(cin>>temp){
if(temp == 0)
break;
friends[i][j] = temp;
j++;
}
}
minM(friends);
return 0;
}
思路:
本來是在全局序列之中求最長上升子序列,但是因爲是重複的序列,
其實只需在第一個序列之中求最長上升序列,並且其中的最大元素在後面的每個序列之中一定存在,最後加上b-1(b爲重複序列個數)
ans[] 存儲給定序列
tmp[i] 表示從第0位到第i位的最長子序列個數
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int a,b;
scanf("%d%d", &a, &b);
vector<int> ans(a, 0),tmp(a,1);
for (int i = 0;i<a;i++)
{
scanf("%d", &ans[i]);
}
for (int i = 1;i<a;i++)
{
for (int j = 0;j<i;j++)
{
if (ans[i]>=ans[j])
{
tmp[i] = max(tmp[i], tmp[j] + 1);
}
}
}
cout << *max_element(tmp.begin(), tmp.end())+b-1;
return 0;
}