这题除开拓扑找环,其它无技巧可言。分类讨论。
想了好久才把情况考虑全面。感觉做题思维还是不够灵敏,不够沉着。
1.基本上每个人都会想到找一个有向环
2.发现只是找有向环的话连第一个样例都过不了,针对第一个样例发现两节点的环有点特殊,两节点的环貌似有一个bug,能够让许多其它的看似无规律的组合合法。然后我的思路过程如下图:
先是这种构型:
做法就是找出所有的上述构型,然后记录最大值。找这个构型就用拓扑排序的算法,每次找0入度的节点就行了,同时要记录每个节点被间接喜欢的最大间接数,这里稍微有点动态规划的感觉。具体写法看代码,那个被间接喜欢的最大间接数就是代码中的cnt数组。
wa了,然后这种构型:
又wa了(我真的傻了才没有再想想,直接写了第二种构型,比第三种构型写法还复杂),然后这种构型:
终于过了。
注意题目说了每个员工只喜欢1个员工,假设一共n个员工,所以图中有n条有向边。因此不可能存在两个有向环连接的情况,就是说每个连通图(注意这里说的是同一个连通图的条件,对于整个图来说是可以有很多有向环的)有且只有一个有向环。
因此第三种构型只用计算所有的两节点环的个数及每个节点被间接喜欢的最大间接数就行了。
代码如下(nansou):
class Solution {
public:
int maximumInvitations(vector<int>& favorite) {
int n=favorite.size();
vector<int> favorited(n,0);
queue<int> que;
for(int i=0;i<n;i++)
favorited[favorite[i]]+=1;
for(int i=0;i<n;i++)
if(!favorited[i])
que.push(i);
vector<int> visited(n,0);
vector<int> cnt(n,0);
while(!que.empty())
{
int u=que.front();
que.pop();
visited[u]=1;
cnt[u]+=1;
int v=favorite[u];
cnt[v]=max(cnt[v],cnt[u]);
favorited[v]--;
if(!favorited[v]) que.push(v);
}
int ret=0;
int cnt_2=0;
for(int i=0;i<n;i++)
{
if(!visited[i])
{
visited[i]=1;
int sum=1;
for(int j=favorite[i];j!=i;j=favorite[j])
sum+=1,visited[j]=1;
if(sum==2)
cnt_2+=2+cnt[favorite[i]]+cnt[i];
else if(sum>2)
ret=max(ret,sum);
}
}
ret=max(ret,cnt_2);
return ret;
}
};