【洛谷 2176】路障
题目描述
每天早晨,FJ从家中穿过农场走到牛棚。农场由 N 块农田组成,农田通过 M 条双向道路连接,每条路有一定长度。FJ 的房子在 1 号田,牛棚在 N 号田。没有两块田被多条道路连接,以适当的路径顺序总是能在农场任意一对田间行走。当FJ从一块田走到另一块时,总是以总路长最短的道路顺序来走。
FJ 的牛呢,总是不安好心,决定干扰他每天早晨的计划。它们在 M 条路的某一条上安放一叠稻草堆,使这条路的长度加倍。牛希望选择一条路干扰使得FJ 从家到牛棚的路长增加最多。它们请你设计并告诉它们最大增量是多少。
输入格式
第 1 行:两个整数 N, M。
第 2 到 M+1 行:第 i+1 行包含三个整数 A_i, B_i, L_i,A_i 和 B_i 表示道路 i 连接的田的编号,L_i 表示路长。
输出格式
第 1 行:一个整数,表示通过使某条路加倍而得到的最大增量。
输入输出样例
输入 #1
5 7 2 1 5 1 3 1 3 2 8 3 5 7 3 4 3 2 4 7 4 5 2
输出 #1
2
说明/提示
【样例说明】
若使 3 和 4 之间的道路长加倍,最短路将由 1-3-4-5 变为 1-3-5。
【数据规模和约定】
对于 30%的数据,N <= 70,M <= 1,500。
对于 100%的数据,1 <= N <= 100,1 <= M <= 5,000,1 <= L_i <= 1,000,000。
题解:最后一个点TLE,吸个organ就可以过了,开心。
普普通通的一个SPFA加上小模拟就可以了哦
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #include<queue> using namespace std; const int N=10001; int x,n,m,u,v,zz,cnt,ans; int dis[N],head[N],vis[N]; struct node{ int val; int next; int to; }e[N]; void add(int x,int y,int z){ e[++cnt].to=y; e[cnt].val=z; e[cnt].next=head[x]; head[x]=cnt; } queue<int>q; int spfa(){ memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); vis[1]=1; dis[1]=0; q.push(1); while(!q.empty()){ x=q.front(); q.pop(); vis[x]=0; for(int i=head[x];i!=0;i=e[i].next){ v=e[i].to; if(e[i].val+dis[x]<dis[v]){ dis[v]=e[i].val+dis[x]; if(vis[v]==0) { vis[v]=1; q.push(v); } } } } return dis[n]; } int main(){ scanf("%d %d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d %d %d",&u,&v,&zz); add(u,v,zz); add(v,u,zz); } int qwq=spfa(); for(int i=1;i<=m;i++){ e[i*2].val*=2; e[i*2-1].val*=2; int jjj=spfa(); ans=max(jjj,ans); //cout<<ans<<endl; e[i*2].val/=2; e[i*2-1].val/=2; } printf("%d\n",ans-qwq); return 0; }
哈(偷偷附上一个优化版本,但是写错了90分……应该没人看见吧)
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #include<queue> using namespace std; const int N=10001; int x,n,m,u,v,zz,cnt,ans; int dis[N],head[N],vis[N]; struct node{ int val; int next; int to; }e[N]; void add(int x,int y,int z){ e[++cnt].to=y; e[cnt].val=z; e[cnt].next=head[x]; head[x]=cnt; } queue<int>q; int pre[N],fr[N],po,ioi[N],nu; int spfa(){ memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); vis[1]=1; dis[1]=0; q.push(1); while(!q.empty()){ x=q.front(); q.pop(); vis[x]=0; for(int i=head[x];i;i=e[i].next){ v=e[i].to; if(e[i].val+dis[x]<dis[v]){ dis[v]=e[i].val+dis[x]; pre[v]=i; fr[v]=x;//*** if(!vis[v]) { vis[v]=1; q.push(v); } } } } return dis[n]; } int main(){ freopen("2176.in","r",stdin); freopen("2176.out","w",stdout); scanf("%d %d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d %d %d",&u,&v,&zz); add(u,v,zz); add(v,u,zz); } int qwq=spfa(); int now=n; while(now!=1){ ioi[++nu]=pre[now];//记路径 now=fr[now]; } for(int i=1;i<=nu;i++){ e[ioi[i]].val*=2; e[ioi[i]^1].val*=2; int jjj=spfa(); ans=max(jjj,ans); //cout<<ans<<endl; e[ioi[i]].val/=2; e[ioi[i]^1].val/=2; } printf("%d\n",ans-qwq); return 0; }