• 银河_lduoj_差分约束_spfa or Tarjan


    Description

    银河中的恒星浩如烟海,但是我们只关注那些最亮的恒星。我们用一个正整数来表示恒星的亮度,数值越大则恒星就越亮,恒星的亮度最暗是 1。现在对于 N 颗我们关注的恒星,有 M 对亮度之间的相对关系已经判明。你的任务就是求出这 N 颗恒星的亮度值总和至少有多大。

    Input

    第一行给出两个整数N和M。
    之后M行,每行三个整数T,A,B,表示一对恒星(A,B)之间的亮度关系。恒星的编号从1开始。
    如果T=1,说明A和B亮度相等。
    如果T=2,说明A的亮度小于B的亮度。
    如果T=3,说明A的亮度不小于B的亮度。
    如果T=4,说明A的亮度大于B的亮度。
    如果T=5,说明A的亮度不大于B的亮度。

    Output

    输出一个整数表示答案。

    Samples

    Input

    5 7
    1 1 2
    2 3 2
    4 4 1
    3 4 5
    5 4 5
    2 3 5
    4 5 1
    

    Output

    11
    

    Hint

    对于30%的数据,N≤100。
    对于100%的数据,N≤100000,M≤100000。

    这个题可以用Tarjan缩点来进行处理
    从题意的制约关系来看,也可以当作差分约束来处理
    当用差分约束的时候,通过题意,我们可以了解到:题目要求我们求出N颗恒星亮度的最小值,那么我们就要求出这N个点亮度之和的最长路
    然后就是普通的SPFA处理,注意在跑SPFA的时候,我们要判断是否存在一个正环,如果说存在一个正环,我们要直接输出-1,因为这个时候他的亮度值会不断的加大:举个例子(1 > 2, 2 > 3, 3 > 4,4 > 1),这个时候我们就要像用SPFA判断是否存在负环的方式来进行判断是否存在正环,在处理的过程中,我们可以记录每个点进入队列的次数,如果说进入队列的次数大于n,说明就会有正环,但是这里其实还会有一种小的优化,如果使用queue的话,会被卡tle,但是如果是用stack就能通过这个题,其实,栈优化的SPFA在不存在负环的时候,会比队列优化的SPFA更快一些

    const int maxn = 1e6 + 7;
    int n, m;
    ll dis[maxn];
    bool vis[maxn];
    struct  node
    {
        int v, nex;
        ll w;
    } e[maxn];
    int cnt, head[maxn];
    int tot[maxn];
    void init()
    {
        for(int i = 0; i <= n; i++)
        {
            dis[i] = -9999999;
            head[i] = -1;
            tot[i] = 0;
        }
    }
    void add(int u, int v, int w)
    {
        e[cnt].v = v;
        e[cnt].w = w;
        e[cnt].nex = head[u];
        head[u] = cnt++;
    }
    int flag = 1;
    void spfa()
    {
        queue <int> st;
        dis[0] = 0;
        st.push(0);
        vis[0] = 1;
        while(st.size())
        {
            int u = st.front();
            st.pop();
            vis[u] = 0;
            for(int i = head[u]; ~i; i = e[i].nex)
            {
                int to = e[i].v;
                if(dis[to] < dis[u] + e[i].w)
                {
                    dis[to] = dis[u] + e[i].w;
                    tot[to] = tot[u] + 1;
                    if(tot[to] > n)
                    {
                        flag = 0;
                        break;
                    }
                    if(vis[to] == 0)
                    {
                        st.push(to);
                        vis[to] = 1;
                    }
                }
            }
            if(flag == 0) break;
        }
    }
    int main()
    {
        cin >> n >> m;
        init();
        for(int i = 1; i <= m; i++)
        {
            int op = read, u = read, v = read;
            if(op == 1) add(u, v, 0), add(v, u, 0);
            else if(op == 2) add(u, v, 1);
            else if(op == 3) add(v, u, 0);
            else if(op == 4) add(v, u, 1);
            else if(op == 5) add(u, v, 0);
        }
        for(int i = 1; i <= n; i++) add(0, i, 1);///超级源点
        spfa();
        /*
        for(int i = 1; i <= n; i++)
        {
            cout << dis[i] << endl;
        }*/
        if(flag)
        {
            ll res = 0;
            for(int i = 1; i <= n; i++)
            {
                res += dis[i];
            }
            cout << res << '\n';
            return 0;
        }
        puts("-1");
        return 0;
    }
    /**
    
    **/
    
    
  • 相关阅读:
    jQuery学习教程(一):入门
    jQuery学习教程(八):事件
    jQuery学习教程(五):选择器综合实例
    jQuery学习教程(六):属性操作与CSS操作
    jQuery学习教程(四):使用jQuery操作DOM
    jQuery学习教程(七):val()与节点操作
    jQuery学习教程(二):选择器1
    const的使用
    ASP.NET 页面间传值的方法
    .net中接口与基类
  • 原文地址:https://www.cnblogs.com/PushyTao/p/15101075.html
Copyright © 2020-2023  润新知