CF 144D Missile Silos [最短路+想法]

题意:

给出一张图和图上的一个顶点,求距离这个点距离为s(最短距离)的顶点或边上的点总共有几个(边上的点要保证也是最短距离)

分析:

先用DIJ求出最短路

然后对所有顶点,距离为s的点都算上

枚举每条边

边上的两个顶点如果距离不够,则看在边上能不能找到一个点,顶点上的距离加上这个顶点到点的距离能为s(注意保证这个距离是最小距离(即这个点通过另外一端的顶点距离源点的距离小大于这个s))。数出这样的点的个数,加上。注意重合点的情况,有的边上一个这样的点都没有,有的只有1个,有的有两个点,有的两个点重合

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
#define pb push_back
using namespace std;
int dis;
int cnt=0;
const int INF=INT_MAX;
const int MAX_V=111111;
struct edge{int from,to,cost,rev,mid;}ed[MAX_V];
typedef pair<int,int>P;
int V;
vector<edge> G[MAX_V];
int d[MAX_V];
int vis[MAX_V];
int ednum;
void dijkstra(int s){
	priority_queue<P,vector<P>,greater<P> > que;
	fill(d+1,d+V+1,INF);
	d[s]=0;
	que.push(P(0,s));
	while(!que.empty()){
		P p=que.top();que.pop();
		int v=p.second;
		if(d[v]<p.first) continue;
		for(int i=0;i<G[v].size();i++){
			edge e=G[v][i];
			if(d[e.to]>d[v]+e.cost){
				d[e.to]=d[v]+e.cost;
				que.push(P(d[e.to],e.to));
			}
		}
	}
}
int main(){
#ifndef ONLINE_JUDGE
	freopen("G:/in.txt","r",stdin);
	//freopen("G:/myout.txt","w",stdout);
#endif
	int n,m,s;
	cin>>n>>m>>s;
	V=n;
	for(int i=1;i<=m;i++){
		int u,v,l;
		cin>>u>>v>>l;
		G[u].pb((edge){u,v,l,G[v].size(),0});
		G[v].pb((edge){v,u,l,G[u].size()-1,0});
		ed[ednum++]=(edge){u,v,l,0,0};
	}
	cin>>dis;
	dijkstra(s);//dij求出最短路
	for(int i=1;i<=n;i++)
        if(d[i]==dis) cnt++;//顶点上的个数
	for(int i=0;i<ednum;i++){
            int fr=ed[i].from;
            int to=ed[i].to;
            int cost=ed[i].cost;
            bool flag=false;
            if(d[fr]<dis){
                if(d[fr]+ed[i].cost>dis){
                    if(d[to]+ed[i].cost-(dis-d[fr])>dis){//保证这端是最短路
                        cnt++;
                    }else if(d[to]+ed[i].cost-(dis-d[fr])==dis){
                        flag=true;//点重合
                        cnt++;
                    }
                }
            }
            if(d[to]<dis){
                if(!flag){//点不重合的时候才算另外一个顶点
                    if(d[fr]+ed[i].cost-(dis-d[to])>dis){
                            cnt++;
                    }
                }
            }
	}
	cout<<cnt<<endl;
}
时间: 2024-10-12 00:01:03

CF 144D Missile Silos [最短路+想法]的相关文章

codeforces 144D Missile Silos(最短路)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Missile Silos A country called Berland consists of n cities, numbered with integer numbers from 1 to n. Some of them are connected by bidirectional roads. Each road has some length. There is

codeforces 144 D. Missile Silos 最短路

链接:http://codeforces.com/problemset/problem/144/D D. Missile Silos time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output A country called Berland consists of n cities, numbered with integer numb

Codeforces 144D. Missile Silos【dijkstra】

题目大意: 给出一个图,一个源点s,问距离这个源点的最短距离恰好为 l 的点有多少个(这个点可以在边上,可以在节点上). 做法: 首先用dijkstra算法求出每个节点到s的最短路d[]数组,然后对于每条边w(u,v)来说有下面三种情况是合法的: 1:d[u]<l && l-d[u]<w(u,v) && d[v]+w(u,v)-(l-d[u])>l 2:d[v]<l && l-d[v]<w(u,v) && d[u

最短路 Codeforces Round #103 (Div. 2) D. Missile Silos

题目传送门 1 /* 2 最短路: 不仅扫描边,还要扫描点:点有两种情况,一种刚好在中点,即从u,v都一样,那么最后/2 3 还有一种是从u,v不一样,两种的距离都是l 4 模板错了,逗了好久:( 5 */ 6 #include <cstdio> 7 #include <algorithm> 8 #include <cstring> 9 #include <cmath> 10 #include <vector> 11 #include <q

【CF】codeforces_1301F_Super Jaber_最短路

题面 codeforces1301F 题解 这题是道简单题 两种走路方式 莽过去,走曼哈顿距离 用超能力.那肯定是三段:先到一个颜色,从这个颜色到另一个颜色,从另一个颜色到目标.其中每一段都可能退化. 我们要算三种:曼哈顿距离,一个点到一种颜色,一种颜色到一种颜色. 第一个随便算,第二种扫四遍,第三种在第二种的基础上Floyd 这种玩意儿会出什么问题那?反正我是溢出了一位. 代码 #include<bits/stdc++.h> #define LL long long #define MAXN

CF 505B Mr. Kitayuta&#39;s Colorful Graph(最短路)

题意  求两点之间有多少不同颜色的路径 范围比较小  可以直接floyd #include<cstdio> #include<cstring> using namespace std; const int N = 105; int d[N][N][N], ans; int main() { int a, b, c, n, m, q; while(~scanf("%d%d", &n, &m)) { memset(d, 0, sizeof(d));

【CF700B】Connecting Universities(想法题,贪心,树上最短路)

题意:给出一棵树上的2*k个节点,给他们配对,使得他们之间的距离和最大. 思路:一条边的两侧如果有一侧没有给定的节点就不会被经过…… 如果有1个节点就会被经过1次…… 如果两侧分别有x,y个给定节点就会被经过min(x,y)次 因为要使总路程最大就是让每一条路被走过最多的次数 肯定是两侧各取一个 剩下的只能在某侧内部解决 所以按此统计即可 答案很大 用INT64 1 var head,vet,next,a,b,c,dep,flag,f:array[1..500000]of longint; 2

CF 383C Propagating tree [想法+树状数组]

题意: 给一棵树 给出两种操作: 1.在某个结点上加上一个值,在这个结点所有的儿子结点上减去这个值,在这个结点的所有孙子结点上加上这个值,在所有曾孙子结点上减去这个值,直到底. 2.查询某个结点上的值 分析: 把这个问题转化为树状数组的区间求和 样例经过dfs处理后如下,每个结点处理出了两个值l,r,层数1,2,3...,层数为奇数的属性为0,层数为偶数的属性为1 可以看到,子树下的结点的两个数值都是包含在子数的根结点的两数范围内的 而子树根结点的兄弟结点的两数范围则不是包含在子树根结点的两数范

CF 241E flights 最短路,重复迭代直到稳定 难度:3

http://codeforces.com/problemset/problem/241/E 首先检测哪些点会出现在从起点到终点的路上,可以用dfs或者迭代, 然后,对于所有的边,设f为边起点,t为边终点,dp[i]为从起点出发到i点所必须花费的时间,则当dp[t]>dp[f]+2,也就是超出限制时,把dp[t]限制到dp[f]+2处,对于dp[f]>dp[t]+1,限制dp[f]到dp[t]+1处 因为这个图没有圈,所以如果存在满足题意的边权方案,那么每次使得一个点的dp值满足要求,n次之后