Fire-Fighting Hero 与 so easy (两个送命题)(附加源点)(并查集)

Fire-Fighting Hero

本题是多源最短路(没有固定汇点),而运行一定数量以上的最短路算法会直接TLE,本题数据范围也不允许使用FLOYD,所以只好加一个附加源点。

附加源点是干什么用的?可以把它看成一个专门通向任意源点的传送门。这个传送门与任意起点都相连,其边的权值为0,从它可以扩展到所有源点,从这些源点开始寻找最短路也就与每一次挑一个源点进行一次最短路搜寻在效果上是等效的,但是时间上极大的优化了。

#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <queue>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#pragma GCC optimize(2)
#pragma warning(disable:4996)
#define lldin(a) scanf("%lld", &a)
#define println(a) printf("%lld\n", a)
#define print(a) printf("%lld ", a)
#define reset(a, b) memset(a, b, sizeof(a))
#define debug cout<<"procedures above are available"<<endl;
#define BigInteger __int128
using namespace std;
const int INF = 2e9 + 2;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1e9 + 7;
//template<typename T>
//inline BigInteger nextBigInteger()
//{
//    BigInteger tmp = 0, si = 1;char c;    c = getchar();
//    while (!isdigit(c))
//{if (c == '-')si = -1;c = getchar();}
//    while (isdigit(c))
//    {tmp = tmp * 10 + c - '0';c = getchar();}
//    return si * tmp;    
//}            
//std::ostream& operator<<(std::ostream& os, __int128 T)
//{
//    if (T<0) os<<"-";if (T>=10 ) os<<T/10;if (T<=-10) os<<(-(T/10));
//    return os<<( (int) (T%10) >0 ? (int) (T%10) : -(int) (T%10) ) ;
//}
//void output(BigInteger x)
//{
//    if (x < 0)
//    {x = -x;putchar('-');}
//    if (x > 9) output(x / 10);
//    putchar(x % 10 + '0');
//    }
/**Maintain your determination.Nobody knows the magnificent landscape
at his destination before the arrival with stumble.**/
/**Last Remote**/
ll arr[99966],sta[95555];
struct node
{
	ll next, to, value;
}nodes[1955555];
ll heads[5909],cnt=0;
void construction(ll from, ll to, ll value)
{
	nodes[cnt] = node{heads[from],to,value };
	heads[from] = cnt++;
}
struct status
{
	ll cur, dis;
	friend bool operator<(status a, status b)
	{
		return a.dis > b.dis;
	}
};
ll dis[57773];
bool vis[57773];
void dijkstra(ll st)
{
	reset(vis, 0);
	reset(dis, 0x3f3f);
	priority_queue<status>pq;
	dis[st] = 0;
	pq.push(status{ st,0 });
	while (!pq.empty())
	{
		status current = pq.top();
		pq.pop();
		if (dis[current.cur] < current.dis)
			continue;
		vis[current.cur] = true;
		for (int i = heads[current.cur]; i != -1; i = nodes[i].next)
		{
			ll t = nodes[i].to;
			if (dis[t] > dis[current.cur] + nodes[i].value)
			{
				dis[t] = dis[current.cur] + nodes[i].value;
				pq.push(status{t,dis[t]});
			}
		}
	}
}
int DETERMINATION()
{
	//ios::sync_with_stdio(false);
	//cin.tie(0),cout.tie(0);
	ll t;
	lldin(t);
	while (t--)
	{
		cnt = 0;
		reset(heads, -1);
		ll points, edge, st, stations, coff;
		lldin(points), lldin(edge), lldin(st), lldin(stations), lldin(coff);
		for (int i = 1; i <= stations; i++)
			lldin(sta[i]);
		for (int i = 1; i <= edge; i++)
		{
			ll tmp1, tmp2, tmp3;
			lldin(tmp1), lldin(tmp2), lldin(tmp3);
			construction(tmp1, tmp2, tmp3);
			construction(tmp2, tmp1, tmp3);
		}
		ll heroes = 0;
		//debug;
		dijkstra(st);
		//debug;
		for (int i = 1; i <= points; i++)
			heroes = max(dis[i], heroes);
		for (int i = 1; i <=stations; i++)
		{
			construction(0, sta[i],0);
			construction(sta[i], 0, 0);
		}
		dijkstra(0);
		ll mx = 0;
		for (int i = 1; i <= points; i++)
		{
			mx = max(mx, dis[i]);
		}
		if (heroes<= mx*coff)
			println(heroes);
		else
			println(mx);
	}
	return 0;
}

So easy

本题是利用并查集,将每个经过合并操作的点的父节点全部设定为题意中的“下一个可用节点”(没有经过合并操作的就是它本身)

比如说1 1 1 1 1五个点,一开始它们的父节点都是自己,将 3 号点变为0,那么三号点就默认和下一个点进行连接,即它的父节点为4号点,若将4号点变为0,那么默认四号点的父节点为五号点,以此类推。

由上述过程可以得知,经过上述处理后,所求点的父节点就是答案。

//#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <queue>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#pragma GCC optimize(2)
#pragma warning(disable:4996)
#define lldin(a) scanf("%lld", &a)
#define println(a) printf("%lld\n", a)
#define print(a) printf("%lld ", a)
#define reset(a, b) memset(a, b, sizeof(a))
#define debug cout<<"procedures above are available"<<endl;
#define BigInteger __int128
using namespace std;
const int INF = 2e9 + 2;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1e9 + 7;
//template<typename T>
//inline BigInteger nextBigInteger()
//{
//    BigInteger tmp = 0, si = 1;char c;    c = getchar();
//    while (!isdigit(c))
//{if (c == '-')si = -1;c = getchar();}
//    while (isdigit(c))
//    {tmp = tmp * 10 + c - '0';c = getchar();}
//    return si * tmp;
//}
//std::ostream& operator<<(std::ostream& os, __int128 T)
//{
//    if (T<0) os<<"-";if (T>=10 ) os<<T/10;if (T<=-10) os<<(-(T/10));
//    return os<<( (int) (T%10) >0 ? (int) (T%10) : -(int) (T%10) ) ;
//}
//void output(BigInteger x)
//{
//    if (x < 0)
//    {x = -x;putchar('-');}
//    if (x > 9) output(x / 10);
//    putchar(x % 10 + '0');
//    }
/**Maintain your determination.Nobody knows the magnificent landscape
at his destination before the arrival with stumble.**/
/**Last Remote**/
unordered_map<ll, ll>mp;
ll check(ll x)
{
	while (mp.count(x)>0)
		x = mp[x];
	return x;
}
void unite(ll x, ll y)
{
	ll hx = check(x);
	ll hy = check(y);
	if (hx != hy)
	{
		mp[hx] = hy;
	}
}
int DETERMINATION()
{
	//ios::sync_with_stdio(false);
	//cin.tie(0), cout.tie(0);
	ll n, q;
	lldin(n), lldin(q);
	for (int i = 1; i <= q; i++)
	{
		ll a, b;
		lldin(a), lldin(b);
		if (a == 1)
			unite(b, b + 1);
		else
		{
			//cout << mp[2] << endl;
			println(check(b));
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值