• hdu 1317 Bellman-Ford


    参考:貌似网上没几个对的题解

    1.http://blog.csdn.net/juststeps/article/details/8772653?reload

    2.wiki:The transitive closure of a directed acyclic graph (DAG) is the reachability relation of the DAG and a strict partial order.

    1.先用floyd求出各点间的可达性,这道题可以包含正负环,所以用floyd算法求出来的类似传递闭包的东西不是传递闭包

    2.运行非队列版的Bellman-Ford算法,对每个点可能地松弛n-1次

    3.再松弛一次,因为不包含正环的图的点肯定不能在松弛了(因为到每个点的路径上最多含n-1个不同的其它点),若某点还能松弛,则说明该图含正环,此时判断能否从源点到该点,能否从该点到终点(1求出的可达性),若两者都满足则winnable。

    其它情况略。

    问题:bford最后的for枚举每条边能保证从源点到达当前点/终点?

    答:

    1.因为有条件的d[i] + val[j] > 0 且 从源点出发不可达点初始化无穷小,所以i点从源点可达;

    2.加上条件adj[i][j](i,j相邻)知j从i可达,再由d[j]<d[i]+val[j]知j点还可继续松弛,即j点在正环中(从而可使j点能量无穷大);

    3.另外又有j与终点连通,所以j点与终点可达。

    综上知,该情况下可从源点到终点,winnable。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<cstdlib>
    #include<algorithm>
    
    using namespace std;
    
    #define LL long long
    #define ULL unsigned long long
    #define UINT unsigned int
    #define MAX_INT 0x7fffffff
    #define MAX_LL 0x7fffffffffffffff
    #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
    #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
    #define INF 10000000
    #define MAXN 111
    
    int val[MAXN], n, d[MAXN];
    bool reach[MAXN][MAXN], adj[MAXN][MAXN];
    
    void floyd(){                           //求可达性
        int k, i, j;
        for(k=1; k<=n; k++)
            for(i=1; i<=n; i++)
                for(j=1; j<=n; j++) if(!reach[i][j])
                    reach[i][j] = reach[i][j] || (reach[i][k] && reach[k][j]);
    }
    
    bool bford(int s, int t){
        int i, k, j;
        for(i=1; i<=n; i++) d[i]=-INF;  d[s]=100;
    
        for(k=0; k<n-1; k++){                   //bellman-ford 
            for(i=1; i<=n; i++)
                for(j=1; j<=n; j++) if(i!=j && adj[i][j]){
                    int tw=d[i]+val[j];
                    if(tw>0) d[j]=MAX(d[j], tw);
                }
        }
    
        for(i=1; i<=n; i++)                     //判断是否含正环
            for(j=1; j<=n; j++) if(adj[i][j] && i!=j && d[i]+val[j]>0 && d[j]<d[i]+val[j])
                if(reach[j][t]) return true;
    
        return d[t]>0;
    }
    
    int main(){
    //    freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
    //    freopen("C:\Users\Administrator\Desktop\out2.txt","w",stdout);
        while(scanf(" %d", &n)==1 && n!=-1){
            int m, u, v;
            memset(reach, 0, sizeof(reach));
            memset(adj, 0, sizeof(adj));
            for(u=1; u<=n; u++){
                scanf(" %d %d", val+u, &m);
                while(m--){
                    scanf(" %d", &v);
                    adj[u][v]=reach[u][v]=true;
                 }
            }
    
            floyd();
    
            if(!reach[1][n]) printf("hopeless
    ");
            else if(bford(1, n)) printf("winnable
    ");
            else printf("hopeless
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    Linux文件系统命令 cd
    Linux文件系统命令 cat
    正则表达式(.+?)与(.+)区别
    Linux文件系统命令 ls
    如何正确认识Docker Kubernetes 和 Apache Mesos
    基于Nutch Solr等基于搭建一体化的数据抓取平台
    ubuntu apache ssl配置
    机器学习入门
    docker 安全性问题
    数据工程师面试必备——Python与数据库的那些事
  • 原文地址:https://www.cnblogs.com/ramanujan/p/3342049.html
Copyright © 2020-2023  润新知