2020.02.07日常总结

C F 144 D     M i s s i l e   S i l o s \color{green}{CF144D\ \ \ Missile\ Silos}

\color{blue}{【题目大意】:} 给定一张 \color{red}{连通的无向图} ,求其中有多少秘密基地。定义一个所谓的秘密基地,就是距离 s s 号点的 \color{red}{最短距离} 恰好等于 k k 的位置,这个位置可以在一个结点上,也可以在一条边的中间。

点数 N N 满足 1 N 1 × 1 0 5 1 \leq N \leq 1 \times 10^5 ,边数 M M 满足 N 1 M m i n ( 1 × 1 0 5 , N × ( N 1 ) 2 ) N-1 \leq M \leq min(1 \times 10^5,\frac{N \times (N-1)}{2}) ,对于任意一条边,边权 w w 满足 1 w 1000 1 \leq w \leq 1000

\color{blue}{【思路】:} 最短路径,想到了什么?对,单源最短路算法!!!因为边权非负,所以我们可以用dijkstra算法。

求出最短路后,对于点,我们可以直接判断它是否为秘密基地。但是,对于边,我们的判断比较复杂,具体地,就是:

  • s s 到边的起点的长度必须 < k <k
  • 从边的起点到秘密基地的距离 < < 边的长度的 1 2 \frac{1}{2} (为了避免重复)

但是,这样虽然没有重复,但有遗漏,即正好在边的 1 2 \frac{1}{2} 的位置的秘密基地我们没有统计,为此,我们要特别判断每条边的一半那个位置。

\color{blue}{【代码】:}

#define ll long long
const int N=1e5+100;
struct edge{
	int next,u,to,len;
}e[N<<1];int h[N],tot;
inline void add(int a,int b,int c){
	e[++tot]=(edge){h[a],a,b,c};h[a]=tot;
	e[++tot]=(edge){h[b],b,a,c};h[b]=tot;
}
priority_queue<pair<ll,int> >q;
ll dis[N];bool vis[N];int n;
const ll inf=1000000000000000ll;
void dijkstra(int s){
	for(int i=1;i<=n;i++){
		vis[i]=true;dis[i]=inf;
	}
	dis[s]=0;q.push(make_pair(0,s));
	while (q.size()){
		pair<int,int> f=q.top();q.pop();
		register int u=f.second;
		if (!vis[u]) continue;
		vis[u]=false;//Remember!!!
		for(int i=h[u];i;i=e[i].next){
			register int to=e[i].to;
			if (dis[to]>dis[u]+e[i].len){
				dis[to]=dis[u]+e[i].len;
				q.push(make_pair(-dis[to],to));
			}
		}
	}
}
int m,ans,start,cnt;ll L;
int main(){
	freopen("t1.in","r",stdin);
	n=read();m=read();start=read();
	for(int i=1;i<=m;i++){
		int u=read(),v=read();
		add(u,v,read());
	}
	dijkstra(start);L=read();
	for(int i=1;i<=n;i++)
		if (dis[i]==L) ans++;
	for(int i=1;i<=tot;i+=2){
		register int u=e[i].u,v=e[i].to,w=e[i].len;
		if (dis[u]<L&&dis[u]+w>L&&w-(L-dis[v])>L-dis[u]) cnt++;
		if (dis[v]<L&&dis[v]+w>L&&w-(L-dis[u])>L-dis[v]) cnt++;
		if (dis[u]<L&&dis[v]<L&&dis[u]+dis[v]+w==(L<<1)) cnt++;
	}
	printf("%d",ans+cnt);
	return 0;
}

C F 260 A     A d d i n g   D i g i t s \color{green}{CF260A\ \ \ Adding\ Digits}

\color{blue}{【题目大意】:} 瓦斯亚有两个数字: a a b b 。然而,瓦斯亚发现数字 a a 太短了 (???)。所以他决定重复这个操作,把 a a 延长 n n 次。

一个数字的加长操作意味着在右边的数字上恰好加上一个数字(十进制),前提是延长后得到的数字可以被Vasya的数字 b b 整除。如果无法得到能被 b b 整除的数,则不能进行延长操作。

你的任务是帮助瓦西娅,并输出最后得到的数字得到的数字。如果不能操作,输出-1

\color{blue}{【输入格式】:}

第一行包含三个整数: a , b , n ( 1 a , b , n 1 × 1 0 5 ) a,b,n(1\leq a,b,n\leq 1 \times 10^5)

\color{blue}{【思路】:} 这是一道考语文的题目,重点在读清楚题目。

在这里插入图片描述
这句话是什么意思?就是 \color{red}{每次} 操作后都要判断是否可以被 b b 整除,如果不能,则撤销这一步操作,要么输出 1 -1 表示无法操作,要么重新进行操作。

那么,解读清楚题目后,算法就很清楚,很简单了,先枚举在 a a 的末尾加一个什么数字( 0 0 9 9 间的数码),看看是否为 b b 的倍数,如果是,重复在新数字的末尾加 0 0 即可。

讲的很笼统(因为我的表述可能不是很好),具体看代码。

\color{blue}{【代码】:}
在这里插入图片描述

发布了103 篇原创文章 · 获赞 4 · 访问量 6732

猜你喜欢

转载自blog.csdn.net/ZHUYINGYE_123456/article/details/104209040