codevs 3983 调整(tweak)

来源:互联网 发布:移动网络优化工作 编辑:程序博客网 时间:2024/06/05 13:29

题目描述 Description
已给定一个N个点M条边的有向图,点编号为1到N,第i条边为 (ui,vi), 权值为wi。你可以进行一次操作,使得任意条边的权值变成非负整数。要求进行尽量少的操作次数,使得点1到点N的最短路径长度变成c
题目保证,c小于在未进行任何操作之前的原图中1到N的最短路长度。

输入描述 Input Description
输入文件tweak.in。
第一行三个整数,NMc
接下来M行,每一条边的信息uiviwi,第i行的表述第i条边的信息。 保证不会有自环存在,对于不同的ij(ui,vi)不同于(uj,vj)

输出描述 Output Description
输出文件 tweak.out。
一行一个整数,要进行最少多少次操作才能使得最短路长度变为c

样例输入 Sample Input
3 3 3
1 2 3
2 3 3
1 3 8

样例输出 Sample Output
1

数据范围及提示 Data Size & Hint
N<=100
M<=1000
0<=c<=100000
0<=wi<=10000
30%数据满足 M<=20
50%数据满足 M<=70

思路
显然每次调整都可以视为是把每条边变为0,最终距离小于等于c都算可行解。
fi,j,k表示ij,将k条边变为0后所得到的最短路长度。那么:

fi,j,0=min(disti,j,fi,k,0+fk,j,0)(1<=k<=n)
fi,j,p=min(fi,x,p1,fi,k,p+fk,j,0)(1<=k<=n,1<=x<=n,xj)

最终输出时输出满足f1,n,i<=c的最小的i

代码

#include <cstdio>#include <cstring>#include <algorithm>const int maxn=100;const int inf=0x3f3f3f3f;int n,m,c,dist[maxn+1][maxn+1];int f[maxn+1][maxn+1][maxn+1];int main(){    memset(dist,63,sizeof dist);    memset(f,63,sizeof f);    scanf("%d%d%d",&n,&m,&c);    for(int i=1; i<=n; i++)    {        dist[i][i]=0;        f[i][i][0]=0;    }    for(int i=1; i<=m; i++)    {        int a,b,v;        scanf("%d%d%d",&a,&b,&v);        dist[a][b]=v;        f[a][b][0]=std::min(f[a][b][0],dist[a][b]);    }    for(int k=1; k<=n; k++)    {        for(int i=1; i<=n; i++)        {            for(int j=1; j<=n; j++)            {                f[i][j][0]=std::min(f[i][j][0],f[i][k][0]+f[k][j][0]);                for(int p=1; p<=n; p++)                {                    if(dist[k][j]!=inf)                    {                        f[i][j][p]=std::min(f[i][j][p],f[i][k][p-1]);                    }                    f[i][j][p]=std::min(f[i][j][p],f[i][k][p]+f[k][j][0]);                }            }        }    }    for(int i=0; i<=n; i++)    {        if(f[1][n][i]<=c)        {            printf("%d\n",i);            break;        }    }    return 0;}
原创粉丝点击