【UOJ 137】行動!行動!
阿新 • • 發佈:2020-10-26
【題目描述】:
大CX國的大兵Jack接到一項任務:敵方佔領了n座城市(編號0~n-1),有些城市之間有雙向道路相連。Jack需要空降在一個城市S,並徒步沿那些道路移動到T城市。雖然Jack每從一個城市到另一個城市都會受傷流血,但大CX國畢竟有著“過硬”的軍事實力,它不僅已經算出Jack在每條道路上會損失的血量,還給Jack提供了k個“簡易保護罩”,一個保護罩可以讓Jack在一條路上的流血量為0。Jack想知道自己最少會流多少血,不過他畢竟是無腦的大兵,需要你的幫助。
【輸入描述】:
第一行有三個整數n,m,k,分別表示城市數,道路數和保護罩個數。
第二行有兩個整數,S,T。分別表示Jack空降到的城市編號和最終要到的城市。
接下來有m行,每行三個整數a,b,c,表示城市a與城市b之間有一條雙向道路。
【輸出描述】:
Jack最少要流的血量。
【樣例輸入】:
5 6 1
0 3
3 4 5
0 1 5
0 2 100
1 2 5
2 4 5
2 4 3
【樣例輸出】:
8
【時間限制、資料範圍及描述】:
時間:1s 空間:128M
對於30%的資料,2<=n<=50, 1<=m<=300, k=0;
對於50%的資料,2<=n<=600, 1<=m<=6000, 0<=k<=1;
對於100%的資料,2<=n<=10000, 1<=m<=50000, 0<=k<=10.
- Universal Online Judge
Server time: 2020-10-26 18:26:14 | 開源專案
題解: 40分做法:沒有藥包時樸素spfa就ok,如果僅有一個藥包列舉邊,刪邊加邊就ojbk
#include<cstdio> #include<iostream> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<bits/stdc++.h> typedef long longll; using namespace std; const int N=100003; const int oo=0x3f3f3f3f; int n,m,K,cnt,x,y,z,S,T; int vis[N],head[N]; ll dis[N],ans=oo; struct node{ int to,next,w; }e[N]; void add(int u,int v,int w){ e[++cnt].to=v; e[cnt].w=w; e[cnt].next=head[u]; head[u]=cnt; } ll spfa(int s,int t){ queue<int>q; memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); dis[s]=0; vis[s]=1; q.push(s); while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(dis[v]>dis[u]+e[i].w){ dis[v]=dis[u]+e[i].w; if(!vis[v]) { q.push(v); vis[v]=1; } } } } if(dis[t]!=oo) return dis[t]; else return -1; } int main(){ freopen("gogo.in","r",stdin); freopen("gogo.out","w",stdout); scanf("%d %d %d",&n,&m,&K); scanf("%d %d",&S,&T); for(int i=1;i<=m;i++){ scanf("%d %d %d",&x,&y,&z); add(x,y,z); add(y,x,z); } if(K==0) { printf("%d\n",spfa(S,T)); return 0; } if(K==1) { for(int i=1;i<=cnt;i+=2){ int yc=e[i].w; e[i].w=0; e[i+1].w; ans=min(ans,spfa(S,T)); e[i].w=yc; e[i+1].w=yc; } printf("%lld\n",ans); return 0; } return 0; }