【BZOJ 3482】 3482: [COCI2013]hiperprostor (dij+凸包)

3482: [COCI2013]hiperprostor

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 277  Solved: 81

Description

在遥远的未来,行星之间的食品运输将依靠单向的贸易路线。每条路径直接连接两个行星,且其运输时间是已知的
。贸易商协会打算利用一项最近发现的新技术——超空间旅行,以增加一些新的航线。通过超空间旅行的航线也是
单向的。由于该项技术仍处于试验阶段,超空间旅行的时间目前是未知的,但它不取决于行星之间的距离,所以每
个超空间旅行的路线将花费等量的时间。下图是三个相互联通的行星及其运输时间的例子。行星使用正整数标号,
超空间旅行时间记为“x”(图片对应第输入样例):过境的时间以天计,并且始终是一个正整数。贸易商协会希
望对引进新航线的后果进行分析:对于某两个行星A和B,他们想知道对于任意的x,从A到B的最短路径的总中转时
间的所有可能的值。例如,在上述情况中,从星球2到星球1的最短路径所需时间可以取值5(如果x≥5),4,3,2
,或1天(如果x<5)

Input

输入的第一行包含两个整数P和R,分别代表行星的数目和航线数量,1≤P≤500,0≤R≤10000。接下来的R条航线
路径包含两或三个整数:行星标号C和D(1≤C,D≤P,C≠D),和T,从C到D的旅行时间。对于传统的路径,T是一
个整数(1≤T≤1000000),超空间航线中,T是字符“x”。 可以存在多行有两个相同的行星。下面的行中包含的
整数Q(1≤Q≤10),表示查询的数量。以下Q行包含两个整数星球标号(A和B,A≠B),为贸易商协会的查询:“
从A到B的最短路径时间的可能值是什么?

Output

输出必须包含q行,每行??一个查询。每一行都必须包含两个整数:不同的可能值的数目和它们的总和。如果不同
的可能值的数目是无限的,该行只输出“inf”。如果没有从A到B的路径,不同的可能值的数目及它们的总和都是0

Sample Input

4 4
1 2 x
2 3 x
3 4 x
1 4 8
3
2 1
1 3
1 4

Sample Output

0 0
inf
3 17

HINT

 2016.6.15新加数据一组,未重测

Source

By Hta

 

 

 

【分析】

  f[i][j]表示走到i,走了j条x边,最短路。【好像spfa会被卡,我就打了dij

  【dij的比较没有打return 调了半天哭死。。。

  若f[i][j]全是INF 就是无解

  若f[i][0]是INF 就是无穷解

  然后其他的,得到i,f[i][ed],写成直线y=i*x+f[i][ed],维护一个凸包。

  他们中间点的个数和值是等差数列,直接求和。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxn 510
  9 #define Maxm 10010
 10 #define LL long long
 11 #define INF 0x7fffffff
 12 
 13 int n,m;
 14 
 15 int read()
 16 {
 17     char ch;
 18     while(!(((ch=getchar())>='0'&&ch<='9')||(ch=='x')));
 19     if(ch=='x') return 0;
 20     int x=ch-'0';
 21     while(((ch=getchar())>='0')&&(ch<='9')) x=x*10+ch-'0';
 22     return x;
 23 }
 24 
 25 struct node
 26 {
 27     int x,y,next,c;
 28 }t[Maxm*2];
 29 int len,first[Maxn];
 30 
 31 void ins(int x,int y,int c)
 32 {
 33     t[++len].x=x;t[len].y=y;t[len].c=c;
 34     t[len].next=first[x];first[x]=len;
 35 }
 36 
 37 struct hp
 38 {
 39     int x,y,dis;
 40     friend bool operator < (hp x,hp y)
 41     {
 42         return x.dis>y.dis;
 43     }
 44 };
 45 
 46 int f[Maxn][Maxn];
 47 priority_queue<hp> q;
 48 void dij(int st)
 49 {
 50     hp nw;nw.dis=0;nw.x=st;nw.y=0;
 51     q.push(nw);f[st][0]=0;
 52     while(!q.empty())
 53     {
 54         nw=q.top();q.pop();
 55         if(nw.dis>f[nw.x][nw.y]) continue;
 56         int x=nw.x;
 57         hp now;
 58         for(int i=first[x];i;i=t[i].next)
 59         {
 60             int y=t[i].y;
 61             if(t[i].c==0)
 62             {
 63                 if(nw.y==n) continue;
 64                 now.x=y;now.y=nw.y+1;now.dis=nw.dis;
 65                 if(f[now.x][now.y]>f[nw.x][nw.y])
 66                 {
 67                     f[now.x][now.y]=f[nw.x][nw.y];
 68                     q.push(now);
 69                 }
 70             }
 71             else
 72             {
 73                 now.x=y;now.y=nw.y;now.dis=f[nw.x][nw.y]+t[i].c;
 74                 if(f[now.x][now.y]>f[nw.x][nw.y]+t[i].c)
 75                 {
 76                     f[now.x][now.y]=f[nw.x][nw.y]+t[i].c;
 77                     q.push(now);
 78                 }
 79             }
 80         }
 81     }
 82 }
 83 struct Line
 84 {
 85     double k,b; 
 86     Line() {}
 87     Line(double nk,double nb) {k=nk;b=nb;}
 88 }P[Maxn];int sl;double tt[Maxn];  
 89  
 90 double pt(double k1,double b1,double k2,double b2)
 91 {
 92     return (b2-b1)/(k1-k2); 
 93 }
 94 
 95 void get_ans()
 96 {
 97     int q=read();int cnt=0;
 98     while(q--)
 99     {
100         int st=read(),ed=read();
101         for(int i=1;i<=n;i++)
102          for(int j=0;j<=n;j++) {f[i][j]=INF;}
103         dij(st);
104         bool pp=0;
105         for(int i=0;i<=n;i++) if(f[ed][i]!=INF) {pp=1;break;}
106         if(!pp) {printf("0 0\n");continue;}
107         if(f[ed][0]==INF) {printf("inf\n");continue;}
108         int num=0;
109         LL sum=0;sl=0; 
110         for(int i=n;i>=0;i--)
111         {
112             if(f[ed][i]==INF) continue; 
113             while(sl>=1&&pt(P[sl].k,P[sl].b,i,f[ed][i])<=tt[sl]) sl--;
114             P[++sl]=Line(i,f[ed][i]);
115             if(sl>1) tt[sl]=pt(P[sl-1].k,P[sl-1].b,P[sl].k,P[sl].b); 
116         }
117         for(int i=1;i<=sl-1;i++)
118         {
119             int l=(int)tt[i]+1,r=(int)tt[i+1];
120             if(l<=r) sum+=(LL)(l*P[i].k+P[i].b+r*P[i].k+P[i].b)*(r-l+1)/2;
121         }
122         num=(int)tt[sl];
123         if(tt[sl]!=num||sl==1) num++,sum+=f[ed][0];
124         printf("%d %lld\n",num,sum);
125     }
126 }
127 
128 int main()
129 {
130     n=read();m=read();
131     len=0;
132     memset(first,0,sizeof(first));
133     for(int i=1;i<=m;i++)
134     {
135         int x,y,c;
136         x=read();y=read();c=read();
137         ins(x,y,c);
138     }
139     get_ans();
140     return 0;
141 }
View Code

【凸包和dij都好弱啊,膜了一下某大神代码。。】

 

2017-03-31 08:17:57

posted @ 2017-03-31 08:18  konjak魔芋  阅读(613)  评论(1编辑  收藏  举报