Description
Input
Output
Sample Input
4 4
1 2 3 4
Sample Output
4
HINT
Source
题意:有n个人,车上有k个座位
然后n个输入,a[i],代表i坐车的先决条件是a[i]必须坐车
思路:这道题是用的图论的方法,图论是我队友主攻,我主要是提供了一些思路
首先,对于成环的情况,这换里面的人都是可以上车的
那么我们把环看成一个点,那么就能形成几条链,那么这些人都是可以上车的
其次,我们要考虑座位的数量,因为有环的话,对于这条链,必然是以环开头,环不满足的话,整条链都不能满足,例如环满足需要四个座位,但是车上只有三个座位,那么这整条链是不满足的
下面的代码是队友的,有爱的同学自己慢慢理解吧。。。
#include<stdio.h>
#include<vector>
#include<string.h>
using namespace std;
const int N = 1005;
int dfn[N],low[N],Stack[N],flag[N],vist[N],num[N],top,deep,tn;
vector<int>mapt1[N],mapt2[N];
void init(int n)
{
for(int i=1;i<=n;i++)
{
mapt1[i].clear();
mapt2[i].clear();
dfn[i]=0;
num[i]=0;
vist[i]=0;
}
tn=top=deep=0;
}
int tt;
void dfs(int u)
{
deep++; vist[u]=tt;
dfn[u]=low[u]=deep;
Stack[++top]=u;
int len=mapt1[u].size();
for(int i=0;i<len;i++)
{
int v=mapt1[u][i];
if(vist[v]==0)
{
dfs(v);
if(low[u]>low[v])
low[u]=low[v];
}
else if(vist[v]==tt&&low[u]>dfn[v])
low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
tn++;
while(u!=Stack[top])
{
flag[Stack[top]]=tn; num[tn]++;top--;
}
flag[Stack[top]]=tn; num[tn]++; top--;
}
}
int in[N],have[N][N];
void rebuilMap(int n)
{
tt=0;
for(int i=1;i<=n;i++)
if(vist[i]==0)
{
tt++;
dfs(i);
}
memset(in,0,sizeof(in));
memset(have,0,sizeof(have));
for(int i=1;i<=n;i++)
{
int u=flag[i];
for(int j=0;j<mapt1[i].size();j++)
{
int v=flag[mapt1[i][j]];
if(u==v||have[v][u])
continue;
in[u]++; have[v][u]=1;
mapt2[v].push_back(u);
}
}
}
int k;
int solve()
{
int dp[N],a[N],m=0;
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=1;i<=tn;i++)
if(in[i]==0&&num[i]<=k)
{
a[m++]=i;
for(int j=k;j>=num[i];j--)
if(dp[j-num[i]]==1)
dp[j]=1;
}
while(m--)
{
int u=a[m];
for(int i=0;i<mapt2[u].size();i++)
{
int v=mapt2[u][i];
in[v]--;
if(in[v]==0&&num[v]<=k)
{
a[m++]=v;
for(int j=k;j>=num[v];j--)
if(dp[j-num[v]]==1)
dp[j]=1;
}
}
}
for(int i=k;i>=0;i--)
if(dp[i])
return i;
return 0;
}
int main()
{
int n;
scanf("%d%d",&n,&k);
{
init(n);
for(int i=1;i<=n;i++)
{
int j;
scanf("%d",&j);
mapt1[i].push_back(j);
}
rebuilMap(n);
printf("%d\n",solve());
}
return 0;
}