tyvj:P1467 通向聚会的道路

Posted fujudge

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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的人。

输出格式

第一行,即距离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 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中的数都可能出现重复数字。
题解
拆点+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 }

 

以上是关于tyvj:P1467 通向聚会的道路的主要内容,如果未能解决你的问题,请参考以下文章

tyvj-1460 旅行

通向膨胀的道路(关于 “separation of concerns” (SoC)的原则)

BZOJ1832 聚会

通向码农的道路(enet开源翻译计划 二)

(转载)通向架构师的道路(第四天)之Tomcat性能调优-让小猫飞奔

luogu P4281 [AHOI2008]紧急集合 / 聚会 |LCA