Hdu 6162 Ch’s gift(Tarjan+dp)

来源:互联网 发布:cm是什么意思网络用语 编辑:程序博客网 时间:2024/05/29 05:57

题目地址: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 debugusing 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;}







原创粉丝点击