H - Bugged System

H - Bugged System

Mr. Light is visiting a city with a “smart” metro system. Or so it seems …

There are exactly n stations in a line, where the ith station is located at a distance xi from the beginning of the line. You can check into some station, travel between the stations as many times as you want in both directions, and check out from another station. The metro card will track the sum of distances you traveled and charge you accordingly once you check out of your destination station.

However, there seems to be a bug in the system; if you happen to check in and out from the same station, you will be charged 0 credit. This creates the possibility of a scenario where one person traveling from stations a to b, and another person traveling from stations b to a, they can now meet up at some station and swap their cards. Therefore when they arrive, they both will pay 0 credit. Check the explanation of the first sample test for another scenario.

A person can go to any number of stations and wait as long as they like. Two people that meet at the same station can swap their cards.

You are given the starting and destination stations for m people traveling along the metro. Is it possible for all m people to check out from their destination stations and pay 0 credit? If so, print the minimum total distance they must travel to achieve this.

Input
The first line of input contains a single integer T (1 ≤ T ≤ 3700), the number of test cases.

The first line of each test case contains two space-separated integers n and m (2 ≤ n, m ≤ 2 × 105), the number of stations and the number of people that will be using the metro stations.

The second line contains n space-separated integers x1, x2, …, xn (0 ≤ xi ≤ 2 × 106), where xi is the distance of the ith station from the beginning of the line.

Each of the following m lines contains two integers si and di (1 ≤ si, di ≤ n, si ≠ di), representing the starting and destination stations of ith person.

The sum of n over all test cases doesn’t exceed 2 × 106, the same is true for m.

Output
For each test case, output on a single line with the minimum total distance all m people need to travel to pay 0 credit.

If it is not possible, output  - 1 on a line.

Example
Input
2
3 3
10 50 25
1 2
2 3
3 1
4 2
1 10 5 3
1 2
4 3
Output
80
-1

Note
First sample explanation:

There are three metro cards, checked in at stations s1, s2, and s3 and with person p1, p2, and p3, respectively.

Person p1 goes to station s2, and swaps cards with person p2. Now person p1 can check out from station s2 with 0 credit (distance traveled 40).

Person p2 now has the card that was checked in from station s1 and goes to station s3 with it. He swaps that card with person p3 and checks out from station s3 with the new card he has (distance traveled 25).

Person p3 now goes to station s1 with the card that was also checked in from station s1 and checks out there with 0 credit (distance traveled 15).

Sum of traveled distances is 40 + 25 + 15 = 80.

思路来源:https://blog.csdn.net/Mitsuha_/article/details/84455292
思路:因为要保证每个人最后都没有付钱,那么每个人的起点是另一个人的终点,最后形成一个环。如果形成了环,那么最短路就是所有人的路径和;否则输出-1。
个人写的稍微复杂了一点,上面传送门的网站,写的要简单很多!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
long long int visit[200005];  //用来记录是否只形成一个环
long long int f[200005];		//用来存头节点	
long long int road[200005]; //用来存每条路的距离信息
long long int find(int x)
{
	if (f[x] == x)
		return x;
	return(f[x] = find(f[x]));
}
void bing(long long int x, long long int y)
{
	long long int f1 = find(x);
	long long int f2 = find(y);
	if (f1 != f2)
		f[f2] = f1;
}
/*上面是并查集模板*/
int main()
{
	freopen("bugged.in", "r", stdin); //此网站不加这个会超时。
	int T;
	scanf("%lld", &T);
	while (T--)
	{
		int flog = 0;
		long long int n, m,t;
		long long int s = 0;
		scanf("%lld%lld", &n, &m);
		for (long long int i = 1; i <= n; i++)
			scanf("%lld", &road[i]);
		for (long long int i = 1; i <= n; i++)
		{
			f[i] = i;
			visit[i] = 0;
		}
		for (long long int i = 1; i <= m; i++)
		{
			long long int a, b;
			scanf("%lld%lld", &a, &b);
			s = s + abs(road[a] - road[b]);
			visit[a]++;			
			visit[b]--;		//核心算法在这里,用来判断是否形成一个首位相接的环。
			bing(a, b);
		}
		for (long long int i = 1; i <=n; i++)
			if (visit[i])
			{
				s = -1;
				break;
			}
		printf("%lld\n", s);
	}
	return 0;
}

刚开始准备用并查集,后来发现,在这个算法里,并查集不是特别适合,并查集无法将环首位相接并且判断为一个环(ps.至少目前我的水平还做不到),后来发现新思路,特别容易判断是否成环的条件,即:使用上面代码的visit数组,具体操作请见代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值