传送门

来源:互联网 发布:荷塘月色淘宝论坛上 编辑:程序博客网 时间:2024/06/11 21:02

问题 D: 传送门

时间限制: 10 Sec  内存限制: 128 MB

题目描述

FJ 每天都要从家里去牧场,再从牧场回家……

FJ从家到牧场的地区可以看作一个N个点和M条双向边的图,家在1号点,牧场在N号点。现在FJ掌握了现代科技,他现在要将一些道路的两端修建双向传送的传送门,这样可以把通过的时间变为0。现在FJ最多可以建K个传送门,FJ想知道他从家到牧场最少需要多少时间?

输入

第一行,三个数N,M,K

接下来M 行,每行三个数,表示一条边的两端和长度

输出

一个数,表示最少要用多长时间

样例输入

4 4 11 2 102 4 101 3 13 4 100

样例输出

1

提示


对于100%的数据,N<=10000,M<=50000,K<=20,答案在int 范围内



对于测试点1~6,时限1s



对于测试点7~9,时限3s



对于测试点10,时限10s

可优化

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iomanip>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
struct edge
{
    int x,y,w,next;
};
struct status
{
    int x,k,dis;
    friend bool operator<(status a,status b)
    {
    return a.dis>b.dis;       
    }
};
priority_queue<status>q;
edge e[100101];
bool v[50101][101];
int dis[50101][101],ls[100101];
int maxE=0;
void add(int x,int y,int w)
{
    e[++maxE]=(edge){x,y,w,ls[x]};
    ls[x]=maxE;
}
int main()
{
 //freopen("in.txt","r",stdin);
    int n,m,k,st,ed;
    scanf("%d%d%d",&n,&m,&k);
    //scanf("%d%d",&st,&ed);
   // cout<<"  @@"<<n<<"   "<<m<<"   "<<k;
    st++;ed=n;
    for (int i=1;i<=m;i++)
    {
        int x,y,w;
        scanf("%d%d%d",&x,&y,&w);
       // x++;y++;
      // cout<<x<<"  "<<y<<"   @@@"<<w<<endl;
        add(x,y,w);
        add(y,x,w);
    }
    st=1;ed=n;
    
    for (int i=0;i<=n;i++)
        for (int j=0;j<=n;j++)
            dis[i][j]=1<<31-1;
            
    dis[st][0]=0;
    status o;
    o.x=st;
    o.k=0;
    o.dis=0;
    //{st,0,0}
    q.push(o);
    //cout<<q.empty()<<"   ((("<<endl; 
    v[st][0]=true;
    
    
    while (!q.empty())
    {
          
        status s=q.top();
        int now=s.x;
        int tmp=s.k;
        int jh=s.dis; 
        //cout<<"  "<<now<<"  !!!"<<tmp<<"   @@@"<<jh;
        q.pop();
        for (int i=ls[now];i;i=e[i].next)
        {
            if (e[i].w+dis[now][tmp]<dis[e[i].y][tmp])
            {
            
                dis[e[i].y][tmp]=e[i].w+dis[now][tmp];
                //cout<<"  "<<"***"<<dis[e[i].y][tmp]<<endl;
                if (!v[e[i].y][tmp])
                {
                    v[e[i].y][tmp]=true;
                    q.push((status){e[i].y,tmp,dis[e[i].y][tmp]});
                }
                
            }
            if (dis[now][tmp]<dis[e[i].y][tmp+1]&&tmp<k)
            {
            
                dis[e[i].y][tmp+1]=dis[now][tmp];
                if (!v[e[i].y][tmp+1])
                {
                    v[e[i].y][tmp+1]=true;
                    q.push((status){e[i].y,tmp+1,dis[e[i].y][tmp+1]});
                }
                
            }
            
        }
        v[now][tmp]=false;
        
    }
    
    //cout<<ed<<"  @@@"<<endl;
    int ans=1<<31-1;
    for (int i=0;i<=n;i++)
        {
        if(dis[ed][i]<ans)
        {
        ans=dis[ed][i];
        //cout<<
        }
       
        }
    printf("%d\n",ans);
   // while(1);
    return 0;
}

原创粉丝点击