给定一个有向图,每条边有两种权:费用和时间。需要寻找一个环,满足这个环的费用之和比时间之和最大。首先考虑相应的判定性问题:是否存在一个环,其费用之比与时间之比大于K。构造一个新图,每个边(i,j)的权W[i][j]=T[i][j]*K-C[i][j],则原图中存在费用与时间之比大于K的环当且仅当这个图中存在负环(把环的费用与时间之比大于K那个式子略微变形就可以得到)。也就是说原图中的这种环与新图中的负环是完全对应的,所以就可以用简单的Bellman-Ford来找负环来解决这个判定性问题。这样的话,原来那个最优性问题就可以用二分答案来解决了。Bellman-Ford找负环且需要输出负环的方法一定要掌握。
[code:cpp]
#include
#include
#include
using namespace std;
const double zero=1e-6,OO=1e20;
const int maxn=60;
int C[maxn][maxn],T[maxn][maxn];
int N;
double W[maxn][maxn];
double dis[maxn];
int father[maxn];
int P;
void input(){
int m;
scanf("%d%d",&N,&m);
memset(C,-1,sizeof(C));
for(int i=0;i<=N;++i){ dis[i]=0; for(int j=1;j<=N;++j){ if(C[i][j]!=-1){ W[i][j]=T[i][j]*K-C[i][j]; } else{ W[i][j]=OO; } } } for(int n=0;n<=N;++n){ bool found=false; for(int i=1;i<=N;++i) for(int j=1;j<=N;++j){ if(dis[i]+W[i][j]hi)break;
}
check(lo);
}
void output(bool suc){
if(!suc){
puts("0");
exit(0);
}
bool vis[maxn];
int path[maxn],end=0;
memset(vis,0,sizeof(vis));
while(!vis[P]){
vis[P]=true;
path[end++]=P;
P=father[P];
}
int beg=0;
for(;path[beg]!=P;++beg);
printf("%d\n",end-beg);
printf("%d",path[beg]);
for(int i=end-1;i>beg;--i)
printf(" %d",path[i]);
putchar('\n');
}
int main(){
input();
solve();
output(true);
}
[/code]