题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6162
思路:
1.强连通分量中的点必定两两可达,可将其看作一点,将图缩点。
2.对于缩点后的图,将其节点的权值设为每个连通分量的节点数。单条路径上的点对于任一点u必定存在一点v使得u可达v。则最多能u达v或v达u的点数为DAG图上权值最大的路径。判断其是否等于总点数即可。
3.dp[u]=max(dp[u],dp[v]+num[u])。
或
将图缩点后,进行拓扑排序,每个阶段若出现多于一个点其入度等于0,则此时不满足要求。任意入度为0的两个点不能相互可达。
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debug
using namespace std;
const int maxn=1000+50;
stack<int> s;
int all,scc,n;
int v[maxn][maxn];
int vis[maxn],m;
int dp[maxn];
int num[maxn];
int belong[maxn],d[maxn];
vector<int> g[maxn],gg[maxn];
int dfn[maxn],low[maxn];
void Tarjan(int u)
{
all++;
dfn[u]=low[u]=all;
s.push(u),vis[u]=1;
for(int i=0; i<g[u].size(); i++)
{
int nt=g[u][i];
if(!dfn[nt])
{
Tarjan(nt);
low[u]=min(low[u],low[nt]);
}
else if(vis[nt])
{
low[u]=min(low[u],dfn[nt]);
}
}
if(low[u]==dfn[u])
{
int v;
scc++;
do
{
v=s.top();
s.pop();
belong[v]=scc;
vis[v]=0;
num[scc]++;
}
while(v!=u);
}
}
void init()
{
all=0,scc=0;
memset(v,0,sizeof(v));
memset(d,0,sizeof(d));
memset(dp,0,sizeof(dp));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(num));
while(!s.empty()) s.pop();
for(int i=0; i<=n; i++)
{
g[i].clear(),gg[i].clear();
}
memset(belong,0,sizeof(belong));
}
int dfs(int u)
{
if(dp[u]) return dp[u];
int tmp=num[u];
for(int i=0;i<gg[u].size();i++)
{
int nt=gg[u][i];
tmp=max(tmp,dfs(nt)+num[u]);
}
return dp[u]=tmp;
}
int solve()
{
for(int i=1; i<=n; i++)
{
if(dfn[i]==0) Tarjan(i);
}
for(int i=1; i<=n; i++)
{
for(int j=0; j<g[i].size(); j++)
{
int nt=g[i][j];
if(belong[i]==belong[nt]) continue;
if(v[belong[i]][belong[nt]]) continue;
gg[belong[i]].push_back(belong[nt]);
d[belong[nt]]++;
v[belong[i]][belong[nt]]=1;
}
}
for(int i=1;i<=scc;i++)
{
if(d[i]==0)
{
dfs(i);
break;
}
}
int ans=0;
for(int i=1;i<=scc;i++)
{
ans=max(dp[i],ans);
}
return ans==n;
}
int main()
{
#ifdef debu
freopen("in.txt","r",stdin);
#endif // debug
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(int i=0; i<m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
}
if(!solve()) printf("Light my fire!\n");
else printf("I love you my love and our love save us!\n");
}
return 0;
}