【BZOJ 3482】 3482: [COCI2013]hiperprostor (dij+凸包)
3482: [COCI2013]hiperprostor
Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 277 Solved: 81Description
在遥远的未来,行星之间的食品运输将依靠单向的贸易路线。每条路径直接连接两个行星,且其运输时间是已知的。贸易商协会打算利用一项最近发现的新技术——超空间旅行,以增加一些新的航线。通过超空间旅行的航线也是单向的。由于该项技术仍处于试验阶段,超空间旅行的时间目前是未知的,但它不取决于行星之间的距离,所以每个超空间旅行的路线将花费等量的时间。下图是三个相互联通的行星及其运输时间的例子。行星使用正整数标号,超空间旅行时间记为“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 4Sample Output
0 0
inf
3 17HINT
2016.6.15新加数据一组,未重测
Source
【分析】
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 }
【凸包和dij都好弱啊,膜了一下某大神代码。。】
2017-03-31 08:17:57