P1948 [USACO08JAN]电话线Telephone Lines

------------------------------

这道题就是我们的sb比赛第四题

-----------------------------

这道题吧,还是很有意思的,需要用到二分,不过用bfs也行(暴力出奇迹)

------------------------------

并且深刻让我感受到了做题时,重构代码的恶心

有时候就是写错了一个字母,但是怎么找还找不出来

--------------------------------

题目链接:Miku

-------------------------------

这道题就是BFS+可能是记忆化?+图论

中心就是记录当前点,用的边数,和最小值,而答案用mink数组储存

因为搜索的原因,最后还要扫一遍

------------------------------

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<cmath>
 8 using namespace std;
 9 //queue<E> q;
10 int max(int x,int y)
11 {
12     if(x>y)
13     return x;
14     else
15     return y;
16 }
17 struct E{
18     int to;
19     int dis;
20     int next;
21 }e[10000*3+666];
22 int tail,headd;//指针 
23 struct bfs{
24 int now;
25 int nowdis;
26 int nowk; 
27 }q[1000000+676];//队列 
28 bfs qu[1000000+676]; 
29 int head[1000+676];
30 int n,m,k;
31 int mink[1005][1005];
32 int p;
33 int x,y,z;
34 void add(int f,int to,int v){
35     p++;
36     e[p].next=head[f];
37     e[p].to=to;
38     e[p].dis=v;
39     head[f]=p;
40     return ;//插入 
41 }
42 inline void in(int now,int k,int dis){
43     qu[tail].now=now;
44     qu[tail].nowdis=dis;
45     qu[tail].nowk=k;
46     tail++;
47     if(tail==1000000+666) tail=0;//循环队列 
48     return ;
49 }
50 void bfss(){
51       while(headd!=tail)
52         {
53             int now,nowk,nowdis;
54             now=qu[headd].now;
55             nowk=qu[headd].nowk;
56             nowdis=qu[headd].nowdis;//取出队首 
57             headd++;
58             if(headd==1000000+666) headd=0;//循环 
59             for(int i=head[now];i;i=e[i].next)
60             {
61                int to=e[i].to;//遍历 
62                //这两个都自带剪枝
63                //就是如果当前值比mink的费用大,就没必要搜索了 
64             if(max(nowdis,e[i].dis)<mink[to][nowk])//这是没用免费边 
65             {//max解决nowdis为零时的情况 
66                 mink[to][nowk]=max(nowdis,e[i].dis);
67                 in(to,nowk,max(nowdis,e[i].dis));
68             }//如果用了免费,那么就有可能是0费,所以不用max 
69             if(nowdis<mink[to][nowk+1]&&nowk<k)//这是使用了免费边的情况 
70             {
71                 mink[to][nowk+1]=nowdis;
72                 in(to,nowk+1,nowdis);
73             }
74         }
75 }
76 }
77 int main(){
78     cin>>n>>m>>k;
79     for(int i=1;i<=m;++i)
80     {
81         cin>>x>>y>>z;
82         add(x,y,z);
83         add(y,x,z);
84     }
85     in(1,0,0);//初始状态 
86     memset(mink,0x3f,sizeof(mink));
87     for(int i=0;i<=k;++i)
88     mink[1][i]=0;//初始化,起始费用为0 
89       bfss(); 
90     int ans=0x7fffffff;
91     for(int i=0;i<=k;++i)
92     ans=min(ans,mink[n][i]);//扫一遍答案(因为这是搜索 
93     if(ans==0x3f3f3f3f) cout<<"-1"<<endl;
94     else
95     cout<<ans<<endl;
96     return 0;
97 }
AC

-------------------------------

如有不当之处,还望指出

----------------------------

That's all.

原文地址:https://www.cnblogs.com/For-Miku/p/10961958.html