tyvj:P1467 通向聚会的道路
背景
Candy住在一个被划分为n个区域的神奇小镇中,其中Candy的家在编号为n的区域,Candy生日这天,大家都急急忙忙赶去Candy家庆祝Candy的生日。
描述
Candy共有t个朋友住在不同的区域。小镇有m条道路,小镇的神奇之处在于其中的p1条道路只会在你走过区域的的个数为奇数时候开启,p2道路只会在你走过区域的个数为偶数的时候开启,剩下的道路一直都会开启。并且,所有的道路只能够单向通过。飘飘乎居士希望知道在所有的好朋友中,谁离Candy最近?。
输入格式
第一行:两个正整数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的人。
接下来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的人。
输出格式
第一行,即距离candy家最近的人的名字,数据保证有且只有一个人为最后的答案。
第二行,该人到candy家的距离。
如果存在多解,则输入名字中字典序较小的一人。
第二行,该人到candy家的距离。
如果存在多解,则输入名字中字典序较小的一人。
测试样例1
输入
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
输出
violethill
4
备注
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中的数都可能出现重复数字。
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中的数都可能出现重复数字。
题解
拆点+spfa。。。tyvj里面题解挺清楚的,这里就不写了,getans为什么只在偶数点里面找答案解释一下:因为初始时走过的区域为0,偶数,所以奇数点意味着这个点不是起点,所以答案不能从奇数点的dis更新得到。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 #define maxn 10005 7 #define maxm 100005 8 #define inf 1<<29 9 int n,m,ecnt,ans=inf,num; 10 int pos[maxn],vis[maxn*2],dis[maxn*2],head[maxn*2]; 11 int odd[maxm],even[maxm],x[maxm],y[maxm],z[maxm]; 12 char name[maxn][20],ansch[20]; 13 struct edge{ 14 int u,v,w,next; 15 }E[maxm*2]; 16 inline int read() 17 { 18 int ret(0); 19 char ch=getchar(); 20 while(ch<'0'||ch>'9')ch=getchar(); 21 while(ch>='0'&&ch<='9') 22 { 23 ret=ret*10+ch-'0'; 24 ch=getchar(); 25 } 26 return ret; 27 } 28 void addedge(int u,int v,int w) 29 { 30 E[++ecnt].u=u; 31 E[ecnt].v=v; 32 E[ecnt].w=w; 33 E[ecnt].next=head[u]; 34 head[u]=ecnt; 35 } 36 void add() 37 { 38 for(int i=1 ; i<=m ; ++i ) 39 { 40 if(odd[i])addedge(y[i],x[i]+n,z[i]); 41 if(even[i])addedge(y[i]+n,x[i],z[i]); 42 if((odd[i]|even[i])==0) 43 { 44 addedge(y[i],x[i]+n,z[i]); 45 addedge(y[i]+n,x[i],z[i]); 46 } 47 } 48 } 49 void spfa() 50 { 51 queue<int> q; 52 memset(dis,127/3,sizeof(dis)); 53 vis[n]=vis[n<<1]=1; 54 dis[n]=dis[n<<1]=0; 55 q.push(n); 56 q.push(n+n); 57 while(!q.empty()) 58 { 59 int d=q.front();q.pop(); 60 vis[d]=0; 61 for(int i=head[d] ; i ; i=E[i].next ) 62 { 63 int v=E[i].v; 64 int w=E[i].w; 65 if(dis[v]>dis[d]+w) 66 { 67 dis[v]=dis[d]+w; 68 if(!vis[v]) 69 { 70 vis[v]=1; 71 q.push(v); 72 } 73 } 74 } 75 } 76 } 77 void getans() 78 { 79 for(int i=1 ; i<=num ; ++i ) 80 { 81 if(dis[pos[i]]<ans) 82 { 83 ans=dis[pos[i]]; 84 memcpy(ansch,name[i],sizeof(name[i])); 85 } 86 if(dis[pos[i]]==ans) 87 if(ansch>name[i]) 88 memcpy(ansch,name[i],sizeof(name[i])); 89 } 90 puts(ansch); 91 printf("%d",ans); 92 } 93 int main() 94 { 95 int k; 96 scanf("%d%d",&n,&m); 97 for(int i=1 ; i<=m ; ++i ){x[i]=read();y[i]=read();z[i]=read();} 98 scanf("%d",&num); 99 for(int i=1 ; i<=num ; ++i ){k=read();odd[k]=1;} 100 scanf("%d",&num); 101 for(int i=1 ; i<=num ; ++i ){k=read();even[k]=1;} 102 scanf("%d",&num); 103 for(int i=1 ; i<=num ; ++i ) 104 { 105 pos[i]=read(); 106 scanf("%s",name[i]); 107 } 108 add(); 109 spfa(); 110 getans(); 111 return 0; 112 }