p1355

好久没写题解了,都怪这道题!

正解好像可以写矩阵乘法,但是!

本题n看似很大,但是考虑最优解一定是跑到一个顶点后在这个边上来回跑,然后看看跑的差不多了再去终点.

这个边一定是最短边么?不一定的,反例可以随便找啦.

这算离散化么...不懂

那么n就可以缩小到T^2了.而且T<=100,每个点有两条边,点最多也就是一整个环,100个点.

这么小的图就可以随便搞了.

那么我们的任务就是处理起点到每个点i走k条边的最短路ds[i][k],终点到每个点i走k条边的最短距离de[i][k].这个处理如果用dfs的话是会超时的,但是可以用类似动态规划的东西

de[i][k]=min(de[e[j].y][k-1]+e[j].v),e[j].x=i;

这样跑一遍的复杂度是T*T,因为每次更新k的距离时T条边总会用两次,即用x更新y,用y更新x.而且图上两个点的最短路最多用T个边,否则一定重复走了某一个边.

然后我们考虑在哪个边上来回跑,这个是不能直接确定的,只好遍历一下.然后考虑用长为几的最短路,这个也不能确定,要搞双重循环.即使如此,复杂度还是优秀的T^3.

我之所以被卡这么长时间的原因完全是初始量不会设,以为自己设的足够大了,但是还是不够用.

using namespace std;
int i,f,k,j,tx,ty,tv,k1,k2;
int n,T,S,E,sum;
struct node
{
    int x,y;
    long long v;
    int next;
}e[210];
int tot,head[110];
long long  de[110][110],ds[110][110],t;
int tt[1010];
long long ans;
void add(int x,int y,long long v)
{
    tot++;
    e[tot].x=x;
    e[tot].y=y;
    e[tot].v=v;
}
long long max(long long a,long long b)
{
    return a>b?a:b;
}
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int main()
{
    n=read();T=read();S=read();E=read();
    for(i=1;i<=T;i++)
    {
        tv=read();tx=read();ty=read();
        tt[tx]=tt[ty]=1;
        add(tx,ty,tv);
        add(ty,tx,tv);
        
    }
    for(i=1;i<=1000;i++)
        if(tt[i])
            sum++,tt[i]=sum;
    S=tt[S];
    E=tt[E];

    for(i=1;i<=tot;i++)
    {
        e[i].x=tt[e[i].x];
        e[i].y=tt[e[i].y];
        e[i].next=head[e[i].x];
        head[e[i].x]=i;
    }
    //cout<<sum<<' ';
    for(i=1;i<=sum;i++)
    {
        for(k=0;k<=T;k++)
            ds[i][k]=de[i][k]=400000000;
    }
    ans=1000000000;
    ds[S][0]=0;
    de[E][0]=0;
    for(k=1;k<=T;k++)
        for(i=1;i<=sum;i++)
            for(j=head[i];j;j=e[j].next)
            {
                ds[i][k]=min(ds[i][k],ds[e[j].y][k-1]+e[j].v);
                de[i][k]=min(de[i][k],de[e[j].y][k-1]+e[j].v);
            }
    for(i=1;i<=tot;i++)
    {
        for(k1=0;k1<=T;k1++)
            for(k2=0;k2<=T;k2++)
            {
                t=n-k1-k2;
                if(t%2==0||t<0)continue;
                t=t*e[i].v;
                ans=min(ans,de[e[i].x][k1]+ds[e[i].y][k2]+t);
                ans=min(ans,de[e[i].y][k1]+ds[e[i].x][k2]+t);
            }
    }
    cout<<ans;
    

}
原文地址:https://www.cnblogs.com/qywyt/p/9717990.html