列表

详情


NC21520. 艾尔重建计划

描述

大主教阿塔尼斯在埃蒙被击败后开始了重建艾尔的计划,要想富,先修路。作为达拉姆的大主教,阿塔尼斯深谙此道,所以他开始重建艾尔的水晶塔折跃网络。不过好在艾尔虽然饱经战火,但是还剩下一些旧的折跃网络,所以只需要添加一些新的高速折跃网络就可以了,但是由于负责此事的一位卡莱工程师F91出了一些差错,他在重建计划中建造了一些多余的折跃网络,当有人提出异议的时候他说“I said the calculation!”(我说了算),暴露了他的Adun理工大学的文凭是花钱买的这个事实。所以收拾烂摊子的任务就到了你的身上,年轻的执政官。不过你的运气很好,F91建造的多余折跃网络都是从艾尔首都出发的,你需要尽可能的拆除这些多余的折跃网络,同时保证所有城市之间的最短折跃时间不变。

输入描述

第一行包括三个整数n,m,k。n代表艾尔一共有n个城市。(2≤n≤105; 1≤m≤3·105; 1≤k≤10),m代表有m条旧的折跃网络,k代表F91建造的所有从首都(首都编号为1)出发的新的折跃网络。

接下来的m行中,每行包含三个数字a,b,c。分别为起点城市,终点城市,折跃时间。

再接下来的k行中,每行包含两个数字x,y。分别为终点城市,折跃时间。(0<a,b,c,x,y<10^9)

输出描述

输出一个整数,为最多可以拆除的新的折跃网络数量。

示例1

输入:

5 5 3
1 2 1
2 3 2
1 3 3
3 4 4
1 5 5
3 5
4 5
5 5

输出:

2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 122ms, 内存消耗: 6460K, 提交时间: 2020-10-08 00:26:06

#include <iostream>
#include <algorithm>
#include <set>
#include <queue>
#include <cstdio>
#include <vector>
#include <map>
#include <stack>
#include <cmath>
using namespace std;
#define For(i, a, b) for(int i = (a), _ = (b); i <= _; i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define maxn 1000000
#define inf 0x7fffffff
int n, m , t;
struct edge{
	int to, dis, next;
}e[maxn];

struct zz{
	int dis, to, z;
}k[maxn];

struct node {
	int dis, pos;
	bool operator < (const node& x) const {
		return x.dis < dis;
	}
};
int tot, first[maxn], x[maxn], y[maxn];
long long dis[maxn];
void add(int a, int b, int c) {
	e[++tot].dis = c; e[tot].to = b; e[tot].next = first[a]; first[a] = tot;
}
int vis[maxn];
priority_queue<node> s;
void dij(int x) {
	dis[1] = 0;
	For(i, 1, n) vis[i] = 0;
	s.push((node) {0, 1});
	while(!s.empty()) {
		node tmp = s.top(); s.pop();
		if (vis[tmp.pos]) continue;
		vis[tmp.pos]++;
		for (int i = first[tmp.pos]; i; i = e[i].next) {
			if (dis[e[i].to] > dis[tmp.pos] + e[i].dis) {
				dis[e[i].to] = dis[tmp.pos] + e[i].dis;
				s.push((node) {dis[e[i].to], e[i].to});
			}
		}
	}
}

bool cmp(zz a, zz b) {
	return a.dis < b.dis;
}
int main(void) {
	cin >> n >> m >> t;
	For(i, 1, n) dis[i] = inf;
	For(i, 1, m) {
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c); add(b, a, c);
	}
	For(i, 1, t) {
		cin >> k[i].to >> k[i].dis;
	}
	dij(1);
	int ans = t;
	sort(k + 1, k + 1 + t, cmp);
	//cout << dis[4] << endl;
	For(i, 1, t) {
		if (dis[k[i].to] > k[i].dis) {
			ans--;
			add(1, k[i].to, k[i].dis);
			dij(1);
		}
	}
	cout << ans << endl;
} 

C++11(clang++ 3.9) 解法, 执行用时: 42ms, 内存消耗: 8548K, 提交时间: 2020-03-14 14:07:39

#include<bits/stdc++.h>
using namespace std;
#define go(i,a,b) for(int i=a;i<=b;i++)
#define maxn 3011010
int tot,dd[maxn],ans,n,m,k;
long long dis[maxn];
struct edge
{
	int x,y,s;
	long long z;
}a[maxn],b[maxn];
bool cmp(edge a,edge b)
{
	return a.z<b.z;
}
void read(long long &x)
{
	x=0;
	long long k=1;
	char s;
	while((s=getchar())!='-'&&s!=EOF&&!isdigit(s));
	if(s=='-')
	{
		k=-1;
		s=getchar();
	};
	while(isdigit(s)) x=x*10+s-'0',s=getchar();
	x=x*k; 
}
void add(int x,int y,long long z)
{
	a[++tot].x=x;
	a[tot].y=y;
	a[tot].z=z;
	a[tot].s=dd[x];
	dd[x]=tot;
}
void spfa(int qd)
{
	queue<int>Q;
	Q.push(qd);
	while(!Q.empty())
	{
		int x=Q.front();
		Q.pop();
		for(int i=dd[x];i;i=a[i].s)
		{
			int y=a[i].y;
			if(dis[y]-dis[x]>a[i].z)
			{
				dis[y]=dis[x]+a[i].z;
				Q.push(y);
			}
		}
	}
}
int main()
{
	long long x,y,z;
	scanf("%d %d %d",&n,&m,&k);
	go(i,1,m)
	{
		read(x);
		read(y);
		read(z);
		add(x,y,z);
		add(y,x,z);
	}
	ans=k;
	for(int i=1;i<=n+1;i++) dis[i]=1e15;
	dis[1]=0;
	spfa(1);
	go(i,1,k)
	{
		read(y);
		read(z);
		b[i].y=y;
		b[i].z=z;
	}
	sort(b+1,b+k+1,cmp);
	go(i,1,k)
	{
		y=b[i].y;
		z=b[i].z;
		if(dis[y]>z)
		{
			ans--;
			dis[y]=z;
			add(1,y,z);
			spfa(y);
		}
	}
	printf("%d",ans);
}

上一题