zoukankan      html  css  js  c++  java
  • 【bzoj2330】 [SCOI2011]糖果

    此题考察差分约束系统,用SPFA求最长路。

    构图,边的权值只为0(等于 大于等于 小于等于)或1(大于 小于),dist数组存最长距离,即该小朋友的最少糖果数。

    一次SPFA之后,直接输出dis数组总和,即为总糖果数。

     

    注意事项:

          1)由于等于是双向边,Node数组开两倍MAXN.

          2)读入判断自环,用flag记录。

          3)如果没有环,不可能有某个点dist大于n,若大于n则必为有环。

          4)q中l与r取模。

          5)答案总和可能大于int,开long long(WA 了好多次,调不出= =).

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
     
    typedef long long LL;
     
    #define MAXN 100010
     
    struct Node
    {
        int next,to,v;
    }e[MAXN<<2];
     
    int cnt;
     
    int n,k;
    int x,a,b;
     
    LL sum;
     
    int l,r;
    int u,v,w;
    int num[MAXN];
    int dist[MAXN],q[MAXN];
     
    bool flag,vis[MAXN];
     
    void link(int u,int v,int w)
    {
        cnt++;
        e[cnt].v=v;
        e[cnt].to=w;
        e[cnt].next=num[u];
        num[u]=cnt;
    }
     
    int SPFA()
    {
        do
        {
            l++;
            u=q[l%MAXN];
            if (dist[u]>n)
                return true;
            for (int i=num[u];i;i=e[i].next)
            {
                v=e[i].v;
                w=e[i].to;
                if (dist[u]+w>dist[v])
                {
                    dist[v]=dist[u]+w;
                    if (!vis[v])
                    {
                        r++;
                        q[r%MAXN]=v;
                        vis[v]=true;
                    }
                }
            }
            vis[u]=false;
        }while(l<r);
        return false;
    }
     
    int main()
    {
        scanf("%d%d",&n,&k);
        for (int i=1;i<=k;i++)
        {
            scanf("%d%d%d",&x,&a,&b);
            switch(x)
            {
                case 1:
                    link(a,b,0);
                    link(b,a,0);
                    break;
                case 2:
                    if (a==b)
                        flag=true;
                    link(a,b,1);
                    break;
                case 3:
                    link(b,a,0);
                    break;
                case 4:
                    if (a==b)
                        flag=true;
                    link(b,a,1);
                    break;
                case 5:
                    link(a,b,0);
                    break;
            }
        }
        for (int i=1;i<=n;i++)
        {
            q[++r]=i;
            dist[i]=1;
            vis[i]=true;
        }
        if (flag || SPFA())
        {
            printf("-1
    ");
            return 0;
        }
        for (int i=1;i<=n;i++)
            sum+=dist[i];
        printf("%lld",sum);
        return 0;
    }
    

      

  • 相关阅读:
    C# 进制转换
    使用Struts1完成用户登录功能
    【Maven实战】仓库介绍和Nexus的安装
    【Maven实战】依赖的聚合和版本管理
    【Maven实战】传递性依赖的问题
    【Maven实战】依赖的范围
    【Maven实战】archetype的使用和eclipse的配置
    【Maven实战】Maven开发环境的搭建和案例展示
    【手机安全卫士02】连接服务器获取更新信息
    【手机安全卫士01】项目Splash页面的开发与设计
  • 原文地址:https://www.cnblogs.com/yangjiyuan/p/5320397.html
Copyright © 2011-2022 走看看