地铁 CSU - 1808

点击打开链接

因为有c值的存在 不满足dp的后效性 所以不能直接跑最短路

要把边抽象为点 将t值当做每个点的点权 每两个点的c值之差当做边权 出发点就是原图中所有和1相连的边对应的点 建立一个超级源点 连向这几个点 目标点就是原图中所有和n相连的边对应的点

还有建图的问题 再建一个新图非常耗时(貌似会比原图稠密很多 比如星形图) 我们可以直接利用原图来跑最短路 详见代码

这道题的复杂度问题有点迷 用spfa就会T 还有就是星形图了 样例中应该是没有 否则dijkstra照样会T吧


#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define N 0x3f3f3f3f3f3f3f3f

struct node1
{
	int u;
	int v;
    ll c;
    ll t;
};

struct node2
{
	int id;
    int v;
    int next;
};

struct node3
{
	bool friend operator < (node3 n1,node3 n2)
	{
		return n1.val>n2.val;
	}
	int id;
	ll val;
};

priority_queue <node3> que;
node1 pre[100010];
node2 edge[200010];
ll point[100010],dis[100010];
int first[100010],book[100010];
int n,m,num;

void addedge(int id,int u,int v)
{
    edge[num].id=id;
    edge[num].v=v;
    edge[num].next=first[u];
    first[u]=num++;
    return;
}

ll getabs(ll a,ll b)
{
	if(a>=b) return a-b;
	else return b-a;
}

ll dijkstra()
{
	node3 cur,tem;
	ll w,minn;
	int i,u,v;
	while(!que.empty()) que.pop();
	memset(dis,0x3f,sizeof(dis));
	memset(book,0,sizeof(book));
	tem.id=m+1,tem.val=0;
	que.push(tem);
	dis[m+1]=0;
	while(!que.empty())
	{
		cur=que.top();//An edge
		que.pop();
		u=cur.id;
		if(book[u]) continue;
		book[u]=1;
		//printf("***%d %lld***\n",u,dis[u]);
		for(i=first[pre[u].u];i!=-1;i=edge[i].next)
		{
			v=edge[i].id;//Another edge
			if(pre[u].c!=-1) w=getabs(pre[u].c,pre[v].c);
			else w=0;
			if(!book[v]&&dis[v]>dis[u]+w+pre[u].t)
			{
				dis[v]=dis[u]+w+pre[u].t;
				tem.id=v,tem.val=dis[v];
				que.push(tem);
				//printf("*%d %lld*\n",v,dis[v]);
			}
		}
		for(i=first[pre[u].v];i!=-1;i=edge[i].next)
		{
			v=edge[i].id;//Another edge
			if(pre[u].c!=-1) w=getabs(pre[u].c,pre[v].c);
			else w=0;
			if(!book[v]&&dis[v]>dis[u]+w+pre[u].t)
			{
				dis[v]=dis[u]+w+pre[u].t;
				tem.id=v,tem.val=dis[v];
				que.push(tem);
				//printf("*%d %lld*\n",v,dis[v]);
			}
		}
	}
	minn=N;
	for(i=first[n];i!=-1;i=edge[i].next)
	{
		v=edge[i].id;
		minn=min(minn,dis[v]+pre[v].t);
	}
    return minn;
}

int main()
{
    int i;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(first,-1,sizeof(first));
        num=0;
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%lld%lld",&pre[i].u,&pre[i].v,&pre[i].c,&pre[i].t);
            addedge(i,pre[i].u,pre[i].v);
            addedge(i,pre[i].v,pre[i].u);
        }
        pre[m+1].u=0,pre[m+1].v=1,pre[m+1].c=-1,pre[i].t=0;
        addedge(m+1,n+1,1);
        printf("%lld\n",dijkstra());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/80158419