zoukankan      html  css  js  c++  java
  • circle

    circle

    题目描述

     

    小w 的男朋友送给小w 一个nn个点mm条边的图,并且刁难小w 要她找出点数最少的正环。

    小w 不会做,于是向你求助。

     

    输入

     

    第一行两个整数n,mn,m。

    接下来mm行,每行四个数u,v,a,bu,v,a,b,表示从uu走到vv的代价为aa,从vv走到uu的代价为bb(算作两条不同的边)。注意a,ba,b可能为负。

     

    输出

     

    当图中包含正环时,输出点数最少的正环(简单环)的点数。

    否则输出0。

     

    样例输入

    3 3
    1 2 2 -1
    2 3 10 -10
    3 1 10 -10

    样例输出

    2

    提示

     

    对于前20%20%的数据,n≤7,m≤10

    对于前60%60%的数据,n≤150,m≤2000

    对于100%100%的数据,1≤n≤300,0≤m≤n(n−1)2,|a|,|b|≤104

    数据保证不存在重边和自环。

     

    来源

    2018年10月hnsdfz集训


    solution

    原题似乎是cf 上的

    令f[k][i][j]表示走2^k 步,i到j的最大距离

    用就像floyd那样 矩阵倍增实现,条件为取max

    如果2^k步是合法的,那么必有一个i满足f[k][i][i]>0

    就像求lca那样按k从大到小往上跳

    就是从大到小枚举k 如果f[k]*ans不合法,那就乘进答案

    这样找到最小的步数

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 305
    #define inf 1e9
    using namespace std;
    int n,m,t1,t2,v1,v2;
    struct node{
        int v[maxn][maxn];
    }f[9];
    node ch(node a,node b){
        node c;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            c.v[i][j]=-inf;
            for(int k=1;k<=n;k++){
                c.v[i][j]=max(c.v[i][j],a.v[i][k]+b.v[k][j]);
            }
        }
        return c;
    }
    int main()
    {
        cin>>n>>m;
        for(int k=0;k<=8;k++)
        for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)f[k].v[i][j]=f[k].v[j][i]=-inf;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&t1,&t2,&v1,&v2);
            f[0].v[t1][t2]=max(f[0].v[t1][t2],v1);
            f[0].v[t2][t1]=max(f[0].v[t2][t1],v2);
        }
        for(int i=1;i<=8;i++)f[i]=ch(f[i-1],f[i-1]);
        node ans,now;int bs=0,flag=0;
        for(int i=8;i>=0;i--){
            if(flag)now=ch(ans,f[i]);
            else now=f[i];
            bool fl=0;
            for(int a=1;a<=n;a++){
                if(now.v[a][a]>0)fl=1;
            }
            if(!fl){bs+=(1<<i);ans=now;flag=1;}
        }
        if(bs+1==512)puts("0");
        else cout<<bs+1<<endl;
        return 0;
    }
     
  • 相关阅读:
    重建二叉树
    从尾到头打印链表
    合并两个数组
    替换空格
    二维数组中的查找
    机器学习中的 precision、recall、accuracy、F1 Score
    rand、randi和randn的区别?
    使用自己的数据集训练和测试"caffenet"
    caffe环境的搭建(Ubuntu14.04 64bit,无CUDA,caffe在CPU下运行)
    Java 并发工具包 java.util.concurrent 用户指南
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358814.html
Copyright © 2011-2022 走看看