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\n");
else if(bford(1, n)) printf("winnable\n");
else printf("hopeless\n");
}
return 0;
}

浙公网安备 33010602011771号