0
点赞
收藏
分享

微信扫一扫

HDOJ 3639 Hawk-and-Chicken

Sikj_6590 2022-08-30 阅读 22


题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3639


此题可能拿到的时候很容易想到直接深搜可能就能解决,但是实际上不行,如果要深搜的话,那我们必须要满足一个条件,那就是不能成环,但是这个题显然是可能有成环的(如样例2),那怎么办呢,这时候我们可以去借助强连通分量来解决这个问题,因为如果我们用Tarjan算法把所有的强连通找到后,再讲所有强连通分量缩点处理后,每个点就满足不会成环的性质,我们就可以进行DFS深搜了,当然在这之前还得反向建图求入度(可以不用反向建图求出度),所以总结此题就是强连通+缩点+反向构图+DFS。


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <stack>
#include <vector>
#define MAXN 5010
using namespace std;
vector<int> g[MAXN],g2[MAXN];
stack<int> st;
int n,index,num,dfn[MAXN],low[MAXN],belong[MAXN];
bool vis[MAXN],instack[MAXN];
int ans[MAXN],in[MAXN],scc[MAXN],sum;
void tarjan(int u)//ÇóÇ¿Á¬Í¨·ÖÖ§
{
int v;
dfn[u] = low[u] = index++;
st.push(u);
instack[u] = true;
vis[u] = true;
for(int i=0; i<g[u].size(); i++)
{
v = g[u][i];
if(!vis[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(instack[v])
low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u])
{
do
{
v = st.top();
instack[v] = false;
st.pop();
belong[v]=num;
scc[num]++;
}while(v != u);
num++;
}
}
void dfs(int u)//ÉîËÑÇó³ö¿Éµ½´ï¸ÃÁ¬Í¨·ÖÖ§µÄµãÊý
{
vis[u]=true;
sum+=scc[u];
for(int i=0; i<g2[u].size(); i++)
if(!vis[g2[u][i]])
dfs(g2[u][i]);
}
int main()
{
int T,m,a,b,cas=0;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
for(int i=0;i<=n;i++)
{
g[i].clear();
g2[i].clear();
}
while(m--)
{
scanf("%d %d",&a,&b);
g[a].push_back(b);
}
index=num=0;
memset(vis,false,sizeof(vis));
memset(instack,false,sizeof(instack));
memset(scc,0,sizeof(scc));
for(int i=0; i<n; i++)
if(!vis[i])
tarjan(i);
memset(in,0,sizeof(in));
for(int i=0; i<n; i++)
for(int j=0; j<g[i].size(); j++)
{
if(belong[i] != belong[g[i][j]])
{
g2[belong[g[i][j]]].push_back(belong[i]);
in[belong[i]]++;
}
}
int maxans=-1;
memset(ans,-1,sizeof(ans));
printf("Case %d: ",++cas);
for(int i=0; i<num; i++)
{
if(in[i]==0)
{
sum=0;
memset(vis,false,sizeof(vis));
dfs(i);
ans[i]=sum;
if(sum>maxans)
maxans=sum;
}
}
printf("%d\n",maxans-1);
int flag=0;
for(int i=0; i<n; i++)
if( ans[belong[i]] == maxans)
{
if(!flag)
{
printf("%d", i);
flag=1;
}
else printf(" %d",i);
}
printf("\n");
}
return 0;
}






举报

相关推荐

0 条评论