codevs 1021 玛丽卡

题目链接:http://codevs.cn/problem/1021/

题解:

  哦!最小值的最大值!!二分!!!……咳咳……

  SPFA算法,邻接表(邻接矩阵应该不会炸,懒得试了……)

  先进行一遍SPFA,用pre数组记录1到n的最短路径,之后枚举这条路径上的每一条边为“堵车”的路,删除该边并进行SPFA,每次进行完与当前ans比较,取较大值

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define MAXN 101000
 6 #define MAXM 3010000
 7 #define INF 214748364//注意,太大了会炸……
 8 int n,m,cnt,d[MAXN],heads[MAXN],q[MAXN],head,tail,pre[MAXN],ans,x,y,z;
 9 bool viss[MAXN];
10 struct node
11 {
12     int u,v;
13     int next;
14     int val;
15 }edge[MAXM];
16 void add(int x,int y,int z)
17 {
18     edge[++cnt].u=x;
19     edge[cnt].v=y;
20     edge[cnt].next=heads[x];
21     edge[cnt].val=z;
22     heads[x]=cnt;
23 }
24 void SPFA(bool _)//_值为true时进行的是第一遍SPFA,需要记录最短路径
25 {
26     head=1;tail=2;
27     q[1]=1;
28     viss[1]=true;
29     while(head<tail)
30     {
31         for(int i=heads[q[head]];i!=0;i=edge[i].next)
32         {
33             if(d[q[head]]+edge[i].val<d[edge[i].v])
34             {
35                 d[edge[i].v]=d[q[head]]+edge[i].val;
36                 if(_)pre[edge[i].v]=i;//记录最短路径,pre存储边的序号
37                 if(!viss[edge[i].v])
38                 {
39                     q[tail++]=edge[i].v;
40                     viss[edge[i].v]=true;
41                 }
42             }
43         }
44         viss[q[head]]=false;
45         head++;
46     }
47 }
48 void __()//枚举最短路径上的每一条边
49 {
50     if(x%2)y=x+1;
51     else y=x-1;//相邻两条单向边记录一条双向边,x,y分别记录两条边的编号
52     z=edge[x].val;
53     edge[x].val=edge[y].val=INF;//设置边权为很大的值相当于删除边
54     for(int i=1;i<=n;i++)d[i]=INF;
55     memset(viss,false,sizeof(viss));
56     d[1]=0;
57     memset(q,0,sizeof(q));
58     SPFA(0);
59     edge[x].val=edge[y].val=z;
60     if(d[n]!=INF)ans=max(d[n],ans);
61     x=pre[edge[x].u];//枚举下一条边
62     if(x==0)return;
63     __();
64 }
65 int main()
66 {
67     scanf("%d%d",&n,&m);
68     for(int i=2;i<=n;i++)d[i]=INF;
69     for(int i=1;i<=m;i++)
70     {
71         scanf("%d%d%d",&x,&y,&z);
72         add(x,y,z);
73         add(y,x,z);
74     }
75     SPFA(1);
76     ans=max(ans,d[n]);//其实可以删掉
77     x=pre[n];
78     __();
79     printf("%d",ans);
80     return 0;
81 }

PS:坑爹的codevs……,数据范围不准确,数组没开够竟然还显示TLE,把程序从递归改到循环之后才从zsc那里了解到这个问题……

循环程序可读性差,放递归程序

  

posted @ 2016-10-15 22:53  xqmmcqs  阅读(184)  评论(0编辑  收藏  举报