[USACO08JAN]电话线Telephone Lines(分层图)/洛谷P1948
这道题其实是分层图,但和裸的分层图不太一样。因为它只要求路径总权值为路径上最大一条路径的权值,但仔细考虑,这同时也满足一个贪心的性质,那就是当你每次用路径总权值小的方案来更新,那么可以保证新的路径权值尽量小。
所以这道题在不删边的情况下可以使用Dij来跑,而删边权的情况就是分层图。
所以就拿分层图来搞好了^_^。
由于这个数据p和k都比较大,所以直接建k+1层图是要爆的,而k+1层图边都一样,我们就用dis[层数(0-k)]来表示。
具体的就是每次Dij转移是要分两种情况:
1.在原层跑,也就是说,在这层中用Dij
2.若下一层边的另一端不够优秀,就用这一层来直接更新,当然就是把这一端的点的解直接复制
大概就是这样了
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct tmp{ 7 int no; 8 int ler; 9 int dis; 10 bool friend operator < (tmp x,tmp y) 11 { 12 return x.dis>y.dis; 13 } 14 }; 15 struct pnt{ 16 int no; 17 int hd; 18 int dis[1005]; 19 bool vis[1005]; 20 }p[1005]; 21 struct ent{ 22 int twd; 23 int lst; 24 int vls; 25 }e[50000]; 26 int n,m,d; 27 int cnt; 28 priority_queue<tmp>Q; 29 void ade(int f,int t,int v) 30 { 31 cnt++; 32 e[cnt].twd=t; 33 e[cnt].lst=p[f].hd; 34 p[f].hd=cnt; 35 e[cnt].vls=v; 36 } 37 int main() 38 { 39 scanf("%d%d%d",&n,&m,&d); 40 for(int i=1;i<=n;i++) 41 { 42 p[i].no=i; 43 for(int j=0;j<=d;j++) 44 { 45 p[i].dis[j]=0x3f3f3f3f; 46 } 47 } 48 p[1].dis[0]=0; 49 for(int i=1;i<=m;i++) 50 { 51 int a,b,c; 52 scanf("%d%d%d",&a,&b,&c); 53 ade(a,b,c); 54 ade(b,a,c); 55 } 56 tmp x; 57 x.no=1; 58 x.ler=0; 59 x.dis=0; 60 Q.push(x); 61 while(!Q.empty()) 62 { 63 x=Q.top(); 64 Q.pop(); 65 int nw=x.no; 66 int t=x.ler; 67 if(x.no==n&&x.ler==d) 68 { 69 printf("%d\n",x.dis); 70 return 0; 71 } 72 if(p[nw].vis[t])continue; 73 p[nw].vis[t]=true; 74 for(int i=p[nw].hd;i;i=e[i].lst) 75 { 76 int to=e[i].twd; 77 if(p[to].dis[t]>max(p[nw].dis[t],e[i].vls)) 78 { 79 p[to].dis[t]=max(p[nw].dis[t],e[i].vls); 80 x=(tmp){to,t,p[to].dis[t]}; 81 Q.push(x); 82 } 83 if(p[to].dis[t+1]>p[nw].dis[t]&&t<d) 84 { 85 p[to].dis[t+1]=p[nw].dis[t]; 86 x=(tmp){to,t+1,p[to].dis[t+1]}; 87 Q.push(x); 88 } 89 } 90 } 91 printf("-1\n"); 92 return 0; 93 } 94 95 telephone line
其实,这道题还可以二分来搞,我就不赘述了主要是我太懒了