【TYVJ】1467 - 通向聚会的道路(spfa+特殊的技巧)
http://tyvj.cn/Problem_Show.aspx?id=1467
这题我并不是看题解a的。但是确实从题解得到了启发。
一开始我就想到一个正解,设d[i][0]表示i开始走过奇数个点的最短路,d[i][1]表示i走过偶数个点的最短路,那么转移很简单
d[v][1]=min(d[v][1], d[u][0]+w(u, v)) 当(u, v)是奇数才能走的边
d[v][0]=min(d[v][0], d[u][1]+w(u, v)) 当(u, v)是偶数才能走的边
然后每一个人都跑一次spfa。。。。。答案为min(d[n][0], d[n][1]),在跑spfa初始化为d[s][1]=0,因为一开始算偶数个
显然tle。。
原因是每一次都跑一次spfa,那么时间无法承受。
看了题解说是逆向建图从n跑spfa,我一想,对啊!
但是有个问题,答案是多少呢。。
答案是d[u][1]没错,也就是说u算偶数个的时候。
但是转移要改。
因为从n跑,所以初始化为d[n][0]=d[n][1]=0,这就会造成奇变偶,偶变奇!
不信你看,当(u, v)这条边是奇边时,且v==n,我们之前的转移转移到的是d[u][1]!但是答案显然不是d[u][1],而是d[u][0],因为这条边是奇边,转移到的是u的偶,但是从u的角度来看,u应该要是奇
如果按原来的转移,那么答案是d[u][0]
我们来转换一下转移
d[v][1]=min(d[v][1], d[u][0]+w(u, v)) 当(u, v)是偶数才能走的边
d[v][0]=min(d[v][0], d[u][1]+w(u, v)) 当(u, v)是奇数才能走的边
那么答案就是d[u][1]了
至于题解说的拆点,我觉得没必要。。。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << #x << " = " << x << endl
#define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; } using namespace std; const int N=10005, M=100005, oo=~0u>>1;
int d[N][2], ihead[N], cnt, vis[N], q[N], tail, front, n, m;
struct ED { int to, next, w, jo; } e[M];
inline void add(const int &u, const int &v, const int &w) {
e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[cnt].w=w;
}
inline const void spfa(const int &s) {
CC(d, 0x3f); CC(vis, 0);
d[s][1]=d[s][0]=tail=front=0; vis[s]=1; q[tail++]=s;
int u, v, w;
while(front!=tail) {
u=q[front++]; if(front==N) front=0; vis[u]=0;
for(int i=ihead[u]; i; i=e[i].next) {
v=e[i].to; w=e[i].w;
if(e[i].jo==1) {
if(d[v][0]>d[u][1]+w) {
d[v][0]=d[u][1]+w;
if(!vis[v]) { vis[v]=1; q[tail++]=v; if(tail==N) tail=0; }
}
}
else if(e[i].jo==2) {
if(d[v][1]>d[u][0]+w) {
d[v][1]=d[u][0]+w;
if(!vis[v]) { vis[v]=1; q[tail++]=v; if(tail==N) tail=0; }
}
}
else {
if(d[v][1]>d[u][0]+w) {
d[v][1]=d[u][0]+w;
if(!vis[v]) { vis[v]=1; q[tail++]=v; if(tail==N) tail=0; }
}
if(d[v][0]>d[u][1]+w) {
d[v][0]=d[u][1]+w;
if(!vis[v]) { vis[v]=1; q[tail++]=v; if(tail==N) tail=0; }
}
}
}
}
}
int main() {
read(n); read(m);
int u, v, w, ans=oo;
char name[30], nm[30];
while(m--) {
read(u); read(v); read(w);
add(v, u, w);
}
read(u); while(u--) e[getint()].jo+=1;
read(u); while(u--) e[getint()].jo+=2;
spfa(n);
read(u); while(u--) {
read(v); scanf("%s", name);
if(ans>d[v][1]) {
ans=d[v][1];
strcpy(nm, name);
}
}
printf("%s\n%d\n", nm, ans);
return 0;
}
背景 Background
Candy住在一个被划分为n个区域的神奇小镇中,其中Candy的家在编号为n的区域,Candy生日这天,大家都急急忙忙赶去Candy家庆祝Candy的生日。
描述 Description
Candy共有t个朋友住在不同的区域。小镇有m条道路,小镇的神奇之处在于其中的p1条道路只会在你走过区域的的个数为奇数时候开启,p2道路只会 在你走过区域的个数为偶数的时候开启,剩下的道路一直都会开启。并且,所有的道路只能够单向通过。飘飘乎居士希望知道在所有的好朋友中,谁离Candy最 近?。
输入格式 InputFormat
第一行:两个正整数n m,表示共n个区域,m条道路
接下来m行,每行三个正整数u v s表示u到v的单向道路,路程为s,其中第i条道路的编号为i。
接着一个整数p1以及p1个正整数odd[i],表示编号为odd[i]的道路只会在走过奇数个区域时开启。
接着一个整数p2以及p2个正整数even[i],表示编号为even[i]的道路只会在走过偶数个区域时开启。
接下来一个正整数 t
紧接着t行,每行一个正整数h以及一个不超过10个字符长度的字符串na(且均有小写字母组成),表示在h区域居住着名字为na的人。
输出格式 OutputFormat
第一行,即距离candy家最近的人的名字,数据保证有且只有一个人为最后的答案。
第二行,该人到candy家的距离。
如果存在多解,则输入名字中字典序较小的一人。
样例输入 SampleInput [复制数据]
4 5
1 2 2
3 4 2
2 4 4
1 3 1
2 3 1
1 4
1 2
2
2 violethill
1 pink
样例输出 SampleOutput [复制数据]
violethill
4
数据范围和注释 Hint
pink尽管从1->3->4距离更近,但因为1->2的这条道路只有在走过奇数个区域时才开启,而pink此时走过的区域为偶数个 (0个)(我们规定,出发点不算走第一个区域),所以pink只好沿1—>2—>3—>4,距离为5;
Violethill尽
管沿2—>3—>4距离为3,但因为3—>4这条道路只有在走过偶数个区域时才开启,当violethill从2到3时,只走了奇数个
(1个)区域,道路不会开启。所以,violethill只好沿2—>4这条道路行走,距离为4,所以violethill比pink更快到
candy家中,并且距离为4。
对于30%的数据 0<n<=100
对于100%的数据0<n<=10000 0<m<=100000
对于所有数据保证两区域间的距离<=100000
数据保证运算即结果在maxlongint以内
数据保证输入的正确性,即至少有一个人可以到达candy家中,并且一个区域最多只有一人,不会出现相同名字的人。
友情提示:可能出现有些道路既在odd中出现,也在even中出现。并且odd或者even中的数都可能出现重复数字。
【TYVJ】1467 - 通向聚会的道路(spfa+特殊的技巧)的更多相关文章
- tyvj1467 通向聚会的道路
背景 Candy住在一个被划分为n个区域的神奇小镇中,其中Candy的家在编号为n的区域,Candy生日这天,大家都急急忙忙赶去Candy家庆祝Candy的生日. 描述 Candy共有t个朋友 ...
- luogu P1462 通往奥格瑞玛的道路--spfa+二分答案
P1462 通往奥格瑞玛的道路 题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡 ...
- 洛谷P1462 通往奥格瑞玛的道路(SPFA+二分答案)
题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛 题目描述 在艾泽拉斯, ...
- [HNOI/AHOI2018]道路
Description: W 国的交通呈一棵树的形状.W 国一共有\(n - 1\)个城市和\(n\)个乡村,其中城市从\(1\)到\(n - 1\) 编号,乡村从\(1\)到\(n\)编号,且\(1 ...
- 【HNOI 2018】道路
Problem Description \(W\) 国的交通呈一棵树的形状.\(W\) 国一共有\(n - 1\)个城市和\(n\)个乡村,其中城市从\(1\)到\(n - 1\) 编号,乡村从\(1 ...
- [HNOI2018]道路 --- 树形DP
[HNOI2018]道路 题目描述: W 国的交通呈一棵树的形状.W 国一共有 \(n-1\) 个城市和 \(n\) 个乡村, 其中城市从 \(1\) 到 \(n-1\) 编号,乡村从 \(1\) 到 ...
- loj #2510. 「AHOI / HNOI2018」道路
#2510. 「AHOI / HNOI2018」道路 题目描述 W 国的交通呈一棵树的形状.W 国一共有 n−1 个城市和 nnn 个乡村,其中城市从 111 到 n−1 编号,乡村从 111 到 n ...
- [HNOI2018]道路(DP)
题目描述 W 国的交通呈一棵树的形状.W 国一共有n−1n - 1n−1 个城市和nnn 个乡村,其中城市从111 到n−1n - 1n−1 编号,乡村从111 到nnn 编号,且111 号城市是首都 ...
- bzoj 1576: [Usaco2009 Jan]安全路经Travel【spfa+树链剖分+线段树】
这几天写USACO水题脑子锈住了--上来就贪心,一交就WA 事实上这个是一个叫最短路树的东西,因为能保证只有一条最短路,所以所有最短路合起来是一棵以1为根的树,并且在这棵树上,每个点被精灵占据的路是它 ...
随机推荐
- PHP编译支持mysqli
PHP编译支持mysqli前提是必须安装mysql直接上命令先进入源码包我的源码包是在/usr/local/php-5.2.1/ext/mysqli这样进入 cd /usr/local/php-5.2 ...
- How to: Set up Openswan L2TP VPN Server on CentOS 6
Have you ever wanted to set up your own VPN server? By following the steps below, you can set up you ...
- 【SpringMVC】SpringMVC系列1之HelloWorld
SpringMVC之HelloWorld 概述 SpringMVC 是基于 MVC 设计理念的优秀Web 框架,是目前最主流的 MVC 框架之一.Spring3.0 后全面超越 Struts2,成为最 ...
- 基础知识《二》java的基本类型
一.java基本数据类型 Java基本类型共有八种,基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byte.short.int.long.float.double.数值类型 ...
- windows2003批量添加和导出所有ip
批量添加IP 在cmd命令行下运行: FOR /L %i IN (130,1,190) DO netsh interface ip add address "本地连接" 192.1 ...
- CSS 样式显示为小手
因为工作需要把鼠标放上去显示小手形状, css样式如下: style="cursor:hand" 部分浏览器支持 style="cursor:pointer&quo ...
- Hibernate常见问题
问题1,hql条件查询报错 执行Query session.createQuery(hql) 报错误直接跳到finally 解决方案 加入 <prop key="hibernate.q ...
- Android之ViewDragHelper
在自定义ViewGroup中,很多效果都包含用户手指去拖动其内部的某个View(eg:侧滑菜单等),针对具体的需要去写好onInterceptTouchEvent和onTouchEvent这两个方法是 ...
- php 指针遍历、预定义数组和常用函数
<?php /*//定义 $attr = array(1,2,3); $attr[] = 1; $attr = array("one"=>"hello&quo ...
- linux shell的切换
查看系统可用shell种类:(一般是bash shell) ➜ ~ chsh -l /bin/sh /bin/bash /sbin/nologin /bin/dash /bin/zsh 修改当前的sh ...