大致题意:
给出一个由n个房子,由若干的单向路连接起来,每个房子都有一个权值,意味着进入这个房子得到或者消耗的能量。把你放在1点,给你100点的初始能量。现在问你能否到达n点且到达时权值大于0.
大致思路:
很好的题目,参考了小媛神的思路 Orz。首先用spfa求最长路,同时判定是否存在正圈,再用floyd求出传递闭包。如果spfa求出的dis[1,n]大于0。或者从起点可以到达某个正圈,且这个正圈可以到达终点,则认为存在可行方案。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
const int nMax=1050;
const int mMax=1000050;
const int inf=1<<28;
struct{
int u,v,next;
int w;
}edge[mMax];
int n, k, edgeHead[nMax];
int dis[nMax],num[nMax];
int stack[nMax],m;
bool vis[nMax];
void addedge(int a,int b,int w){
edge[k].w = w;
edge[k].u=a;
edge[k].v=b;
edge[k].next=edgeHead[a];
edgeHead[a]=k;k++;
}
int eng[nMax];
bool map[nMax][nMax];
bool spfa(int s){
int i,top=0;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++)dis[i]=0;
dis[s]=100;
stack[++top]=s;
vis[s]=true;
num[s]++;
while(top){
int u=stack[top--];
vis[u]=false; /////////////////
if(num[u]>n)break;
for(i=edgeHead[u];i!=0;i=edge[i].next){
int v=edge[i].v;
if(dis[v]<dis[u]+edge[i].w){
dis[v]=dis[u]+edge[i].w;
if(!vis[v]){
vis[v]=true;
stack[++top] = v;
num[v]++;
}
}
}
}
if(dis[n]>0){
return 1;
}
return 0;
}
int main(){
int i,j,a,b,c,s,t;
while(scanf("%d",&n)&&n>0){
k=1;
memset(map,0,sizeof(map));
memset(edgeHead,0,sizeof(edgeHead));
for(i=1;i<=n;i++){
scanf("%d%d",&eng[i],&m);
for(j=0;j<m;j++){
scanf("%d",&a);
addedge(i,a,0);
map[i][a]=1;
}
}
for(i=1;i<k;i++){
edge[i].w=eng[edge[i].v];
}
// for(i=1;i<k;i++){
// cout<<"fuck "<<edge[i].u<<" "<<edge[i].v<<" "<<edge[i].w<<"\n";
// }
memset(num,0,sizeof(num));
if(spfa(1)){
printf("winnable\n");
}
else{
bool flag=0;
for(k=1;k<=n;k++){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
if(map[i][k]&&map[k][j]){
map[i][j]=1;
}
}
}
}
for(i=1;i<=n;i++){
if(map[1][i]&&map[i][n]){
if(num[i]>n){
flag=1;
break;
}
}
}
if(flag){
printf("winnable\n");
}
else{
printf("hopeless\n");
}
}
}
return 0;
}
分享到:
相关推荐
swift 闭包+嵌套函数+extension+单例+嵌套函数
Warshall算法的基本思想是通过迭代的方式逐步构造传递闭包,每次迭代都会检查当前关系中是否存在一条路径,使得两个未被确定为有关系的元素之间存在传递关系。 C++程序实现Warshall算法通常涉及以下步骤: 1. 初始...
离散实验报告求有限集上给定关系的自反、对称和传递闭包 在离散数学实验报告中,我们将学习如何求有限集上给定关系的自反、对称和传递闭包。这些概念是离散数学的重要组成部分,对于理解关系闭包的性质和应用具有...
离散数学-关系,集合,求自反闭包,对称闭包,传递闭包 离散数学-关系,集合,求自反闭包,对称闭包,传递闭包 离散数学-关系,集合,求自反闭包,对称闭包,传递闭包 离散数学-关系,集合,求自反闭包,对称闭包...
《利用Warshall算法求二元关系的可传递闭包》 在离散数学中,二元关系是一个重要的概念,它描述了集合中的元素之间是否存在某种特定的联系。当需要研究这些关系并探究其性质时,有时我们需要计算关系的传递闭包。...
### 传递闭包Matlab程序知识点详解 #### 一、模糊聚类分析与传递闭包算法简介 在数据挖掘和模式识别领域,模糊聚类分析是一种广泛应用的技术,它通过将对象划分为不同的模糊集合来揭示数据中的结构。与传统的硬...
传递闭包是图论中的一个概念,特别是在有向图中,它表示了图中所有节点间的可达性。在数学上,传递闭包是关系R的一种扩展,使得对于任何节点i和j,如果存在一系列节点i到j的路径,使得沿着这些路径应用关系R后,最终...
### C++ 求解传递闭包算法解析 #### 一、传递闭包概念 在图论中,传递闭包(Transitive Closure)是针对有向图的一种特殊运算,其目的是找出图中任意两个顶点间是否存在路径。简单来说,如果存在一条从顶点 \( i \...
自反、对称和传递闭包运算实现 本文主要介绍了使用 C 语言实现自反闭包、对称闭包和传递闭包运算的方法和算法。通过实验和编程,了解关系运算的原理和实现过程。 1. 自反闭包的设计 自反闭包是关系运算中的一种...
关系的传递闭包是图论和离散数学中的一个重要概念,它在计算机科学,特别是数据库理论和算法设计中有着广泛的应用。在这个实验中,我们主要关注如何使用C++语言实现关系的传递闭包。 首先,关系的传递闭包是指在一...
离散数学中传递闭包是用Warshall算法求的,此程序正式这种算法的C语言实现
Warshall传递闭包算法,使用C++实现Warshall传递闭包算法,对正在学习算法的同学应该挺有帮助的
这里我们将详细讨论如何用C语言实现传递闭包、自反闭包和对称闭包这三种闭包算法。 首先,我们需要理解这些闭包的定义: 1. **传递闭包**:在一个关系集合中,如果对于所有的元素a、b和c,只要a与b有关系且b与c有...
根据给定文件的信息,我们可以深入探讨“传递闭包”的概念及其在计算机科学中的实现方法。 ### 传递闭包的概念 传递闭包(Transitive Closure)是集合论中的一个概念,指的是在集合\(X\)上的一类特殊的二元关系。...
Warshall 算法的传递闭包实现 在计算机科学中,Warshall 算法是一种常用的图算法,用于计算图的传递闭包。传递闭包是指图中所有可能的路径的集合。 Warshall 算法的传递闭包可以用来解决许多实际问题,如计算二分图...
而传递闭包是指在有向图中,对于任意两个节点i和j,如果存在一个节点k使得i可以通过k到达j,则称i与j在传递意义上是相关的。 Warshall算法的基本思想是通过一系列的矩阵运算来求解这个问题。在数学表示上,我们可以...
本实验旨在通过编程实践的方式帮助学习者深入理解关系闭包的概念,并熟练掌握Warshall算法用于计算关系的自反闭包、对称闭包以及传递闭包。 #### 关键概念解释 1. **自反闭包**:给定集合A上的关系R,如果对于集合...
做模糊聚类分析时判断模糊矩阵传递性并计算传递闭包MATLAB实现,,可以算出模糊传递矩阵,当矩阵满足自反性对称性时为等价矩阵
实验名称:Warshall算法计算关系的传递闭包 源代码: #include using namespace std; int add(int a,int b) {if(a==0&&b==0) return 0; else if(a==0&&b==1||a==1&&b==0||a==1&&b==1) return 1; else cout...