码迷,mamicode.com
首页 > 其他好文 > 详细

Travel Guide

时间:2020-05-16 18:59:20      阅读:58      评论:0      收藏:0      [点我收藏+]

标签:queue   travel   jks   operator   开始   force   mod   continue   gui   

链接: 2018-2019 ICPC Southwestern European Regional Programming Contest (SWERC 2018)

题意:

一个无向图,图上有三个关键点A,B,C,统计图上点u的个数,满足没有其他点v到A,B,C的最短距离都比u到A,B,C的最短距离小(uA>=vA && uB>=vB && uC>=vC &&(uA>vA || uB>vB || uC>vC) )

解法:

先跑3次dijkstra,求出所有点到A,B,C的距离,然后按照到A的距离从小到大排序。从前往后遍历,用线段树查询此时<=b的最小C值,如果比当前C大,该点就加入答案中。

考虑到距离相等的情况,先用map去重,并记录重复点的个数,每次加入答案的就是点的个数。

因为距离最大有5e7,需要把距离离散化

代码:

#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;
const int maxn = 1e5 + 5;
const int maxm = 2e5 + 5;
struct node {
	int id, cost;
	node(int a = 0, int b = 0) :id(a), cost(b) {}
	bool operator<(const node &b)const {
		return cost > b.cost;//将小的放上面
	}
};
struct edge {
	int v, cost;
	edge(int a = 0, int b = 0) :v(a), cost(b) {}
};
vector<edge>E[maxm];
int dis[3][maxn];
bool vis[maxn];
void dijkstra(int n, int start,int *lowcost) {
	fill(vis + 1, vis + 1 + n, 0);
	fill(lowcost + 1, lowcost + 1 + n, INF);
	priority_queue<node>q;
	lowcost[start] = 0;
	q.push(node(start, 0));
	while (!q.empty()) {
		int u = q.top().id;
		q.pop();
		if (vis[u])continue;
		vis[u] = 1;
		for (int i = 0; i < E[u].size(); i++) {
			int v = E[u][i].v;
			int cost = E[u][i].cost;
			if (!vis[v] && lowcost[v] > lowcost[u] + cost) {
				lowcost[v] = lowcost[u] + cost;
				q.push(node(v, lowcost[v]));
			}
		}
	}
}
void addedge(int u, int v, int w) {
	E[u].push_back(edge(v, w));
}
struct Point{
    int a,b,c;
    operator<(const Point &B)const{
        if(a!=B.a){
            return a<B.a;
        }
        else if(b!=B.b){
            return b<B.b;
        }
        else{
            return c<B.c;
        }
    }
}p[maxn];
int lisan[maxn*3];
int lisancnt=0;

//------线段树-------------
const int M=1<<19;//从1开始,不能修改0和M
int T[M+M];
void modify(int n,int v){
	for(T[n+=M]=v,n>>=1;n;n>>=1)
		T[n]=min(T[n+n],T[n+n+1]);
}
int query(int l,int r){
	int rmin=INF,lmin=INF;
	for(l+=M-1,r+=M+1;l^r^1;l>>=1,r>>=1){
		if(~l&1) lmin=min(lmin,T[l^1]);
		if(r&1) rmin=min(rmin,T[r^1]);
	}
	return min(lmin,rmin);
}
//------------------------

int main() {
	int n, m, u, v, w;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++) {
		scanf("%d%d%d", &u, &v, &w);
		u++; v++;
		addedge(u, v, w);
		addedge(v, u, w);
	}
	dijkstra(n, 1, dis[0]);
	dijkstra(n, 2, dis[1]);
	dijkstra(n, 3, dis[2]);
	for (int i = 1; i <= n; i++) {
		p[i]={dis[0][i],dis[1][i],dis[2][i]};
	}
	map<Point,int>MA;
	for(int i=1;i<=n;i++){
        lisan[++lisancnt]=p[i].a;
        lisan[++lisancnt]=p[i].b;
        lisan[++lisancnt]=p[i].c;
	}
	sort(lisan+1,lisan+1+lisancnt);
	int lisansize=unique(lisan+1,lisan+1+lisancnt)-(lisan + 1);
	for(int i=1;i<=n;i++){
        p[i].a=lower_bound(lisan+1,lisan+1+lisansize,p[i].a)-lisan;
        p[i].b=lower_bound(lisan+1,lisan+1+lisansize,p[i].b)-lisan;
        p[i].c=lower_bound(lisan+1,lisan+1+lisansize,p[i].c)-lisan;
        MA[p[i]]++;
	}
	int cnt=0;
	for(auto poi:MA){
        p[++cnt]=poi.first;
	}
	sort(p+1,p+1+cnt);
    int ans=0;
    fill(T,T+M+M-1,INF);
    for(int i=1;i<=cnt;i++){
        if(query(1,p[i].b)>p[i].c){//该点是有用的
            ans+=MA[p[i]];
            modify(p[i].b,p[i].c);
        }
    }
    printf("%d\n",ans);
}
/*
5 4
0 3 1
1 3 1
2 3 1
4 3 1

5 6
0 3 1
1 3 1
2 3 1
4 3 1
0 1 1
0 2 1
*/

Travel Guide

标签:queue   travel   jks   operator   开始   force   mod   continue   gui   

原文地址:https://www.cnblogs.com/ucprer/p/12901437.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!