zoukankan      html  css  js  c++  java
  • Father Christmas flymouse--POJ3160Tarjan

    Father Christmas flymouse


    Time Limit: 1000MS Memory Limit: 131072K

    Description

    After retirement as contestant from WHU ACM Team, flymouse volunteered to do the odds and ends such as cleaning out the computer lab for training as extension of his contribution to the team. When Christmas came, flymouse played Father Christmas to give gifts to the team members. The team members lived in distinct rooms in different buildings on the campus. To save vigor, flymouse decided to choose only one of those rooms as the place to start his journey and follow directed paths to visit one room after another and give out gifts en passant until he could reach no more unvisited rooms.

    During the days on the team, flymouse left different impressions on his teammates at the time. Some of them, like LiZhiXu, with whom flymouse shared a lot of candies, would surely sing flymouse’s deeds of generosity, while the others, like snoopy, would never let flymouse off for his idleness. flymouse was able to use some kind of comfort index to quantitize whether better or worse he would feel after hearing the words from the gift recipients (positive for better and negative for worse). When arriving at a room, he chould choose to enter and give out a gift and hear the words from the recipient, or bypass the room in silence. He could arrive at a room more than once but never enter it a second time. He wanted to maximize the the sum of comfort indices accumulated along his journey.

    Input

    The input contains several test cases. Each test cases start with two integers N and M not exceeding 30 000 and 150 000 respectively on the first line, meaning that there were N team members living in N distinct rooms and M direct paths. On the next N lines there are N integers, one on each line, the i-th of which gives the comfort index of the words of the team member in the i-th room. Then follow M lines, each containing two integers i and j indicating a directed path from the i-th room to the j-th one. Process to end of file.

    Output

    For each test case, output one line with only the maximized sum of accumulated comfort indices.

    Sample Input

    2 2
    14
    21
    0 1
    1 0

    Sample Output

    35

    Hint

    32-bit signed integer type is capable of doing all arithmetic.

    Source

    POJ Monthly–2006.12.31, Sempr

    题意:Flymouse从武汉大学ACM集训队退役后,做起了志愿者,在圣诞节来临时,Flymouse要打扮成圣诞老人给集训队员发放礼物。集训队员住在校园宿舍的不同寝室,为了节省体力,Flymouse决定从某一个寝室出发,沿着有向路一个接一个的访问寝室并顺便发放礼物,直至能到达的所有寝室走遍为止。对于每一个寝室他可以经过无数次但是只能进入一次,进入房间会得到一个数值(数值可正可负),他想知道他能获得最大的数值和。

    思路:对于一个有向图,图中的强连通一定可以相互抵达,所以Flymouse可以访问强连通分量中的任意元素,对于集合中的负值不要,只要正值就可以保证得到的值最大,所以我们将强连通缩点后形成一个DAG图,搜索一下就可以得到最大值。


    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    const int Max = 30010;
    
    vector<int>Map[Max];
    
    vector<int>G[Max];
    
    vector<int>P[Max];
    
    int va[Max]; //节点价值
    
    int dfn[Max],low[Max],vis[Max],dep;//遍历的顺序,回溯,标记,遍历的顺序。
    
    int pre[Max],num,a[Max];// 集合,数目,集合价值
    
    stack<int>S;
    
    int n,m;
    
    void init() //初始化
    {
        for(int i=0;i<=n;i++)
        {
            Map[i].clear();
    
            P[i].clear();
    
            G[i].clear();
        }
    
        memset(vis,0,sizeof(vis));
    
        memset(a,0,sizeof(a));
    
        dep  = 0 ; num = 0;
    }
    
    void Tarjan(int u)
    {
        dfn[u] = low[u] =dep++;
    
        vis[u]=1;
    
        S.push(u);
    
        for(int i=0;i<Map[u].size();i++)
        {
            if(vis[Map[u][i]]==1)
            {
                low[u] = min(low[u],dfn[Map[u][i]]);
            }
    
            else if(vis[Map[u][i]]==0)
            {
                Tarjan(Map[u][i]);
    
                low[u] = min(low[u],low[Map[u][i]]);
            }
        }
    
        if(dfn[u]==low[u])
        {
            while(!S.empty()) //缩点 
            {
                int v = S.top();
    
                S.pop();
    
                pre[v] = num;
    
                vis[v] = 2;
    
                a[num]+=va[v];
    
                G[num].push_back(v);//记录集合的点
    
                if(u==v)
                {
                    break;
                }
            }
            num++;
        }
    }
    
    int dfs(int u)
    {
        if(!vis[u])
        {
            int ans = 0;
    
            vis[u]=1;
    
            for(int i=0;i<P[u].size();i++)
            {
                ans = max(ans,dfs(P[u][i]));
            }
    
            a[u] += ans ;
        }
    
        return a[u]; 
    }
    
    int main()
    {
        while(~scanf("%d %d",&n,&m))
        {
    
            init();
    
            for(int i=0;i<n;i++) //先输入价值
            {
                scanf("%d",&va[i]);
    
                va[i]=va[i]<0?0:va[i];//小于零的归零,为不访问
            }
    
            int u,v;
    
            for(int i=0;i<m;i++) //建图
            {
                scanf("%d %d",&u,&v);
    
                Map[u].push_back(v);
            }
    
            for(int i=0;i<n;i++)//强连通缩点
            {
                if(vis[i]==0)//从未被遍历的点搜索
                {
                    Tarjan(i);
                }
            }
    
            for(int i=0;i<num;i++) //重新建图
            {
                memset(vis,0,sizeof(vis));
    
                for(int j=0;j<G[i].size();j++)
                {
                    int u=G[i][j];//集合中的点
    
                    for(int k=0;k<Map[u].size();k++)
                    {
                        if(pre[Map[u][k]] != i && !vis[pre[Map[u][k]]])
                        {
                            P[i].push_back(pre[Map[u][k]]);
    
                            vis[pre[Map[u][k]]] = 1;
                        }
                    }
                }
            }
    
            int ans= 0 ;
    
            memset(vis,0,sizeof(vis));
    
            for(int i=0;i<num;i++)//搜索最大的值
            {
                ans = max(ans,dfs(i));
            }
    
            printf("%d
    ",ans);
    
        }
        return 0;
    }
  • 相关阅读:
    window.location.Reload()和window.location.href 区别
    PHP substr(),mb_substr()及mb_strcut的区别和用法
    jstree节点展开设置
    关于Jquery中ajax方法data参数用法
    HTML相对路径(Relative Path)和绝对路径(Absolute Path)
    Win32基础编程了解窗口类
    Visual C++ ActiveX 开发指南:第一章 什么是ActiveX
    分粥
    蛙蛙推荐:ASP实现自定义标签模板
    蛙蛙请教:如何利用委托实现多个方法同时调用.
  • 原文地址:https://www.cnblogs.com/juechen/p/5255887.html
Copyright © 2011-2022 走看看