Tyvj 1221 微子危机——战略
背景
Summer联盟战前兵力战略转移。
描述
Summer一共拥有N个星球(1~N),你要把这N个星球上的兵力转到第M个星球上。本来每个星球之间都有星际轨道连接,但Guiolk监视了某些轨道,我们一但走上这些轨道,有可能受到他的攻击。为了安全,Summer不会走被监视的轨道。于是,只有L个星际轨道是被批准通过的。Summer的国防部想统计一下所需的最短路程(即每个星球到第M星球的最短路程总和,单位:M PS:'M'不是米)。
输入格式
输出格式
测试样例1
输入
【样例输入1】
5 3 6
1 2 1
1 3 3
2 3 1
4 1 5
4 5 2
5 1 2
【样例输入2】
5 3 4
1 2 1
1 3 3
2 3 1
5 1 2
输出
【样例输出1】
13 M(s) are needed.
【样例输出2】
Sth wrong.
备注
对于80%的数据,1≤N≤600 , L≤180000
对于100%的数据,1≤N≤1000 , 1≤M≤N , L≤500000, 1≤a,b≤N , 0≤c≤10000。
2010年广州市第二中学初二第二次测试第三题。
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<vector> 6 #include<queue> 7 #include<algorithm> 8 #define mx 1001 9 10 using namespace std; 11 struct orz 12 { 13 int d,p; 14 friend bool operator <(orz a,orz b) {return a.d>b.d;}//堆和set里面都只有小于号,所以要用小根堆的话要将<重定向为> 15 }; 16 struct Edge{ 17 int to; 18 int w; 19 }; 20 priority_queue < orz > ss; 21 int flag = 0,v[mx],d[mx],n,m,l; 22 vector<Edge> edge[mx]; 23 void input(){ 24 cin>>n>>m>>l; 25 int u,v,wei; 26 Edge test; 27 for(int i = 1;i <= l;i++){ 28 scanf("%d%d%d",&u,&v,&wei); 29 test.to = v; 30 test.w = wei; 31 edge[u].push_back(test); 32 test.to = u; 33 edge[v].push_back(test); 34 } 35 for(int i = 0;i < mx;i++) d[i] = 1000000000; 36 } 37 void dij(int s) 38 { 39 40 d[s]=0; 41 orz tmp; 42 tmp.d=0,tmp.p=s; 43 ss.push(tmp); 44 flag++; 45 int x,dd; 46 Edge j; 47 while (!ss.empty())//不能只做n次,要一直做到堆空 48 { 49 tmp=ss.top(); 50 ss.pop(); 51 x=tmp.p,dd=tmp.d; 52 if (v[x]==flag) continue;//这里一定要判断!!! 53 v[x]=flag; 54 for (int i = 0;i < edge[x].size();i++){ 55 56 j = edge[x][i]; 57 if (d[j.to]>dd+j.w) 58 { 59 d[j.to]=dd+j.w; 60 tmp.d=dd+j.w,tmp.p=j.to; 61 ss.push(tmp); 62 } 63 } 64 65 } 66 } 67 int main(){ 68 input(); 69 dij(m); 70 int ans = 0; 71 for(int i = 1;i <= n;i++){ 72 if(i == m) continue; 73 if(d[i] >= 1000000000){ 74 cout<<"Sth wrong."<<endl; 75 return 0; 76 } 77 ans+=d[i]; 78 } 79 cout<<ans<<" M(s) are needed."<<endl; 80 return 0; 81 }
2015山东信息学夏令营 Day5T3 路径
问题描述:
给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用。
输入:
第一行包含一个正整数n,表示点数。
接下来n行,每行包含两个整数x[i],y[i](0<=x[i],y[i]<=10^9),依次表示每个点的坐标。
输出:
一个整数,即最小费用。
输入输出样例:
|
path.in |
path.out |
|
5 |
2
|
数据范围:
对于30%的数据,1<=n<=100;
对于60%的数据,1<=n<=1000;
对于全部的数据,1<=n<=200000;
思路:
1、60分直接最短路
2、对于坐标系中连续的三个点,(x1,y1),(x2,y2),(x3,y3),总有min(x2-x1,y2-y1) + min(x3-x2,y3-y2) ≤ min(x3 - x1,y3 - y1),所以在建图的时候,可以按x,y分别排一遍序,然后,相邻的点建边,这样边数为2*n,再用堆dij就可以了
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 #include<vector> 7 #include<queue> 8 #define maxn 200005 9 #define inf ~0U>>1 10 using namespace std; 11 struct point{ 12 int x; 13 int y; 14 int pos; 15 }; 16 struct orz{ 17 int p; 18 int d; 19 friend bool operator < (orz a,orz b){ 20 return a.d > b.d; 21 } 22 }; 23 struct edge{ 24 int v; 25 int w; 26 }; 27 priority_queue< orz > ss; 28 vector<edge> g[maxn]; 29 point pt[maxn]; 30 int flag = 0,v[maxn],d[maxn],n; 31 bool cmpa(point a,point b){ 32 return a.x < b.x; 33 } 34 bool cmpb(point a,point b){ 35 return a.y < b.y; 36 } 37 void init(){ 38 cin>>n; 39 int tx,ty; 40 for(int i = 1;i <= n;i++){ 41 scanf("%d%d",&tx,&ty); 42 pt[i].x = tx; 43 pt[i].y = ty; 44 pt[i].pos = i; 45 } 46 for(int i = 1;i <= n;i++) d[i] = inf; 47 sort(pt+1,pt+1+n,cmpa); 48 edge tmp; 49 for(int i = 1;i < n;i++){ 50 tmp.w = pt[i+1].x - pt[i].x; 51 tmp.v = pt[i + 1].pos; 52 g[pt[i].pos].push_back(tmp); 53 tmp.v = pt[i].pos; 54 g[pt[i+1].pos].push_back(tmp); 55 } 56 sort(pt+1,pt+1+n,cmpb); 57 for(int i = 1;i < n;i++){ 58 tmp.w = pt[i+1].y - pt[i].y; 59 tmp.v = pt[i + 1].pos; 60 g[pt[i].pos].push_back(tmp); 61 tmp.v = pt[i].pos; 62 g[pt[i+1].pos].push_back(tmp); 63 } 64 } 65 void dij(){ 66 orz tmp; 67 d[1] = 0; 68 tmp.p = 1; 69 tmp.d = 0; 70 ss.push(tmp); 71 flag++; 72 int to,wei,x,dd; 73 edge j; 74 while(!ss.empty()){ 75 tmp = ss.top(); 76 ss.pop(); 77 x = tmp.p; 78 dd = tmp.d; 79 if(v[x] == flag) continue; 80 v[x] = flag; 81 for(int i = 0;i < g[x].size();i++){ 82 j = g[x][i]; 83 to = j.v; 84 wei = j.w; 85 if(d[to] > dd + wei){ 86 d[to] = dd + wei; 87 tmp.d = dd + wei; 88 tmp.p = to; 89 ss.push(tmp); 90 } 91 } 92 } 93 cout<<d[n]; 94 } 95 int main(){ 96 97 init(); 98 dij(); 99 return 0; 100 }
2015山东信息学夏令营 Day4T3 生产
【题目描述】
工厂为了生产一种复杂的产品,给各个生产部门制定了详细的生产计划。那么,就经常会有生产部门要把产品送到另一个生产部门作为原料。这是一个注重产品质量的工厂,所以每当有产品要从A部门运到B部门时,都要先从A部门送到质量检验处,检验合格后再从质量检验处运到B部门。
有些部门之间有传送带连接,厂长想知道每次将产品从一个部门运送到另一个部门最少需要多长时间。
【输入格式】
第一行两个整数n、m,n表示部门数量,m表示传送带数量。出于方便,1号部门是质量检验处。
接下来m行,每行三个整数u、v、w,表示有一条从u部门到v部门的传送带,传送过去需要w个单位时间。注意传送带是单向的。
接下来一个整数q,表示有q次运送。
接下来q行,每行两个数a、b,表示这一次要将产品从a部门运送到b部门。
【输出格式】
输出q行,每行一个整数,表示这次运送最少需要的时间。若没有传送方案,输出-1。
【样例输入】
5 5
1 2 3
1 3 5
4 1 7
5 4 1
5 3 1
3
4 2
5 3
2 3
【样例输出】
10
13
-1
【数据规模与约定】
30%的数据,n≤100,m≤500,w=1
60%的数据,n≤100,m≤5000
另20%的数据,q=1
100%的数据,2≤n≤3000,m≤100000,2≤a,b≤n,
q≤100000,1≤u,v≤n,1≤w≤10000
有些部门之间可能有多条传送带。
工厂的员工都非常尽职尽责,他们的认真和热情决定了产品的完美,所以不必考虑产品不合格的情况。
思路:
1、最短路,A到1再到B的距离,等于1到B的距离加上1到A的距离
2、存者正反两个图,在反图上求1到A距离,在正图上求1到B的距离
代码:
①官方标程(spfa + 链式前向星)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N = 3050; 6 const int M = 500050; 7 const int inf = 987654321; 8 int n,m,q; 9 struct Edge 10 { 11 int u,v,w; 12 }xu[M]; 13 int point[N],to[M],next[M],val[M]; 14 int dui[N],mina[N],minb[N],top,tail; 15 bool indui[N]; 16 void MakeMinLen(int x[]) 17 { 18 int i; 19 dui[1]=1; 20 top=0;tail=1; 21 indui[1]=1; 22 for(i=1;i<=n;i++) 23 x[i]=inf; 24 x[1]=0; 25 while(top^tail) 26 { 27 top++; 28 if(top==N) 29 top=0; 30 int now=dui[top]; 31 int then=point[now]; 32 indui[now]=0; 33 while(then) 34 { 35 int tox=to[then]; 36 if(x[tox]>x[now]+val[then]) 37 { 38 x[tox]=x[now]+val[then]; 39 if(!indui[tox]) 40 { 41 indui[tox]=1; 42 tail++; 43 if(tail==N) 44 tail=0; 45 dui[tail]=tox; 46 } 47 } 48 then=next[then]; 49 } 50 } 51 } 52 void InitGraph() 53 { 54 int i; 55 scanf("%d%d",&n,&m); 56 for(i=1;i<=m;i++) 57 scanf("%d%d%d",&xu[i].u,&xu[i].v,&xu[i].w); 58 memset(point,0,sizeof point); 59 for(i=1;i<=m;i++) 60 { 61 next[i]=point[xu[i].v]; 62 point[xu[i].v]=i; 63 to[i]=xu[i].u; 64 val[i]=xu[i].w; 65 } 66 MakeMinLen(mina); 67 memset(point,0,sizeof point); 68 for(i=1;i<=m;i++) 69 { 70 next[i]=point[xu[i].u]; 71 point[xu[i].u]=i; 72 to[i]=xu[i].v; 73 val[i]=xu[i].w; 74 } 75 MakeMinLen(minb); 76 } 77 void MakeAns() 78 { 79 scanf("%d",&q); 80 while(q--) 81 { 82 int a,b; 83 scanf("%d%d",&a,&b); 84 int res=mina[a]+minb[b]; 85 if(res>=inf) 86 res=-1; 87 printf("%d\n",res); 88 } 89 } 90 int main() 91 { 92 freopen("data.in","r",stdin); 93 freopen("data.out","w",stdout); 94 InitGraph(); 95 MakeAns(); 96 return 0; 97 }