HDU - 5636 Shortest Path (判断最短路)

211 篇文章 1 订阅
47 篇文章 1 订阅
HDU - 5636
Time Limit: 2000MS Memory Limit: 131072KB 64bit IO Format: %I64d & %I64u

 Status

Description

There is a path graph   with   vertices. Vertices are numbered from   to   and there is an edge with unit length between   and    . To make the graph more interesting, someone adds three more edges to the graph. The length of each new edge is 

You are given the graph and several queries about the shortest path between some pairs of vertices.
 

Input

There are multiple test cases. The first line of input contains an integer  , indicating the number of test cases. For each test case: 

The first line contains two integer   and     -- the number of vertices and the number of queries. The next line contains 6 integers    , separated by a space, denoting the new added three edges are 

In the next   lines, each contains two integers   and    , denoting a query. 

The sum of values of   in all test cases doesn't exceed  .
 

Output

For each test cases, output an integer  , where   is the answer for  -th query.
 

Sample Input

        
        
1 10 2 2 4 5 7 8 10 1 5 3 1
 

Sample Output

        
        
7
本来想着用模拟来将,所有的情况模拟,但发现当包含三条边时,情况太多了,模拟了一个小时,直接就崩溃了,还是另寻他路吧!!!
看了大神的博客,他是用DFS写的,50行就解决了,这对于我这个dfs渣渣来说实在是太难了。。
DFS的思路是:
在每次查询时,可以分四种情况
1、一条边都不加;
2、只加入一条边;
3、加入两条边;
4、三条边都加入;
一直模拟到3条边都加入,找到最小的距离就行了。
#include<stdio.h>  
#include<string.h>  
#include<math.h>  
#include<algorithm>  
#include<iostream>  
#include<queue>  
#define INF 0x3f3f3f3f  
#define IN __int64  
#define ull unsigned long long  
#define ll long long  
#define N 100010  
#define M 1000000007  
using namespace std;  
ll ans,sum;
int vis[5];
int n,m,a[5][2],x,y;
void dfs(int k,int now,int dis)
{
	if(dis+abs(now-y)<ans)
		ans=dis+abs(now-y);
	if(k>3)
		return ;
	for(int i=0;i<3;i++)
	{
		if(!vis[i])
		{
			vis[i]=1;
			dfs(k+1,a[i][0],dis+abs(now-a[i][1])+1);
			dfs(k+1,a[i][1],dis+abs(now-a[i][0])+1);
			vis[i]=0;
		}
	}
}
int main()
{
	int t,i;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(i=0;i<3;i++)
			scanf("%d%d",&a[i][0],&a[i][1]);
		memset(vis,0,sizeof(vis));
		sum=0;
		for(i=1;i<=m;i++)
		{
			scanf("%d%d",&x,&y);
			ans=abs(x-y);
			dfs(1,x,0);
			sum=(sum+i*ans)%M;
		}
		printf("%I64d\n",sum);
	}
	return 0;
}

 
//WA了考虑的太少。。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<queue>
#define INF 0x3f3f3f3f
#define IN __int64
#define ull unsigned long long
#define ll long long
#define N 100010
#define M 1000000007
using namespace std;
struct zz
{
	int x;
	int y;
	int l;
}p[N];
int cmp(zz a ,zz b)
{
	if(a.x==b.x)
		return a.y<b.y;
	return a.x<b.x;
}
int main()
{
	int t;
	int n,m;
	int i,j,k;
	int x,y,s,e;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(i=0;i<3;i++)
		{
			scanf("%d%d",&p[i].x,&p[i].y);
			if(p[i].x>p[i].y)
			{
				int tt=p[i].x;p[i].x=p[i].y;p[i].y=tt;
			}
			p[i].l=p[i].y-p[i].x;
		}
		sort(p,p+3,cmp);
		ll sum=0;
		for(i=1;i<=m;i++)
		{			
			scanf("%d%d",&s,&e);
			int ss=-1,ee=-1;
			int l=e-s;
			if(s>e)
			{
				int tt=s;s=e;e=tt;
			}			
			for(j=0;j<3;j++)
			{
				if(s<=p[j].x)
				{
					ss=j;
					break;
				}
			}
			for(j=2;j>=0;j--)
			{
				if(e>=p[j].y)
				{
					ee=j;
					break;
				}
			}
			int kl=0;
			if(ss==ee)
				sum=(sum+(l-p[ss].l+1)*i)%M;
			else if(ss<ee)
			{
				for(j=ss;j<=ee;j++)
					kl+=p[j].l;
				sum=(sum+(l-kl+1)*i)%M;
			}
			else
				sum=(sum+l*i)%M;
		}
		printf("%lld\n",sum);
	}
	return 0;
}
//开始时用的是SPFA写,超时了,
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<queue>
#define INF 0x3f3f3f3f
#define IN __int64
#define ull unsigned long long
#define ll long long
#define N 100010
#define M 1000000007
using namespace std;
struct zz
{
	int from;
	int to;
	int val;
	int next;
}edge[N];
int head[N],edgenum;
int n,m;
int dis[N];
int vis[N];
void add(int u,int v,int w)
{
	zz E={u,v,w,head[u]};
	edge[edgenum]=E;
	head[u]=edgenum++;
}
void SPFA(int x)
{
	queue<int>q;
	memset(vis,0,sizeof(vis));
	memset(dis,INF,sizeof(dis));
	q.push(x);
	dis[x]=0;
	vis[x]=1;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i!=-1;i=edge[i].next)
		{
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].val)
			{
				dis[v]=dis[u]+edge[i].val;
				if(!vis[v])
				{
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
}
int main()
{
	int t;
	int i,j,k;
	int x,y,s,e;
	scanf("%d",&t);
	while(t--)
	{
		memset(head,-1,sizeof(head));
		edgenum=0;
		scanf("%d%d",&n,&m);
		for(i=1;i<n-1;i++)
		{
			add(i,i+1,1);
			add(i+1,i,1);
		}
		for(i=0;i<3;i++)
		{
			scanf("%d%d",&x,&y);
			add(x,y,1);
			add(y,x,1);
		}
		SPFA(1);
		int sum=0;
		for(i=1;i<=m;i++)
		{
			scanf("%d%d",&s,&e);
			
//			printf("%d\n",dis[e]);
			sum=(sum+i*(abs)(dis[e]-dis[s]))%M;
		}
		printf("%d\n",sum);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值