2019ICPC(南昌) - Fire-Fighting Hero(最短路+思维)
題目鏈接:點(diǎn)擊查看
題目大意:有一個(gè)由n個(gè)點(diǎn),m條邊組成的無(wú)環(huán)無(wú)向圖,題目保證是連通圖,現(xiàn)在每個(gè)點(diǎn)代表一個(gè)著火點(diǎn),有一個(gè)消防英雄和k個(gè)消防隊(duì)伍比賽救火,他們的具體位置輸入時(shí)會(huì)給出,誰(shuí)的分?jǐn)?shù)低誰(shuí)就獲勝,分?jǐn)?shù)的定義如下:
消防英雄:到每個(gè)著火點(diǎn)的最短路中的最大值除以題目中給出的C
消防隊(duì)伍:從k個(gè)隊(duì)伍中選擇最優(yōu)的一個(gè)消防隊(duì)伍(即下半句話中描述的分?jǐn)?shù)最小的隊(duì)伍),也是取到每個(gè)著火點(diǎn)的最短路中的最大值
如果消防英雄獲勝,輸出消防英雄的原分?jǐn)?shù),如果消防隊(duì)伍獲勝,輸出消防隊(duì)伍的原分?jǐn)?shù),如果平局,算是消防英雄獲勝
題目分析:這個(gè)題超級(jí)坑。。一點(diǎn)是比賽時(shí)的答疑區(qū),出題老師把題意說(shuō)錯(cuò)了,雖然并不影響我們隊(duì)做不出這個(gè)題orz,其次就是建邊不好想,想到了就是簡(jiǎn)單的兩邊迪杰斯特拉,想不到就是暴力弗洛伊德,但我們暴力走的給的回饋卻是WA,有點(diǎn)自閉。。說(shuō)一下正解吧,就是將k個(gè)點(diǎn)之間建邊,邊權(quán)為0,這樣就相當(dāng)于將k個(gè)點(diǎn)視為一個(gè)點(diǎn),然后對(duì)一個(gè)點(diǎn)跑一邊迪杰斯特拉,就能直接求出來(lái)k個(gè)點(diǎn)中到達(dá)某一點(diǎn)的最短路了,最后維護(hù)一下最大值即可,簡(jiǎn)單易懂。。但我們想不出來(lái),利用這個(gè)思想也可以直接維護(hù)一個(gè)距離數(shù)組dis[N],然后也是跑一遍迪杰斯特拉,只不過(guò)這次初始化的時(shí)候?qū)個(gè)點(diǎn)都預(yù)先扔進(jìn)優(yōu)先隊(duì)列中,并將dis[i]初始化為0,扔進(jìn)去讓他自己跑答案去吧。。有點(diǎn)bfs搜索的思想,不過(guò)主體還是將k個(gè)點(diǎn)視為一個(gè)點(diǎn),學(xué)到了,真的學(xué)到了。
有個(gè)小細(xì)節(jié)就是,最后為了避免出現(xiàn)浮點(diǎn)數(shù),消防英雄除以C,變成消防隊(duì)伍乘以C即可,爆不了int
上代碼吧,兩個(gè)代碼大同小異:
令第一個(gè)隊(duì)伍為中心點(diǎn),與其他隊(duì)伍建邊權(quán)為0的邊:
#include<iostream> #include<string> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<cstdio> #include<queue> using namespace std; typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e3+100;int n,m,s,k,c;int team[N];int maze[N][N];struct Node {int id,dis;Node(int ID,int DIS){id=ID;dis=DIS;}bool operator<(const Node &a)const{return dis>a.dis;} };priority_queue<Node>q;int d[N];bool vis[N];void Dijkstra(int s) {while(!q.empty())q.pop();for(int i=1;i<=n;i++){d[i]=inf;vis[i]=false;}d[s]=0;q.push(Node(s,0));while(!q.empty()){Node temp=q.top();q.pop();int u=temp.id;int w=temp.dis;if(vis[u])continue;vis[u]=true;for(int i=1;i<=n;i++){if(d[i]>d[u]+maze[u][i]){d[i]=d[u]+maze[u][i];q.push(Node(i,d[i]));}}} } int main() {int w;cin>>w;while(w--){scanf("%d%d%d%d%d",&n,&m,&s,&k,&c);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)maze[i][j]=i==j?0:inf;for(int i=1;i<=k;i++)scanf("%d",team+i);while(m--){int u,v,w;scanf("%d%d%d",&u,&v,&w);if(maze[u][v]>w)maze[u][v]=maze[v][u]=w;}Dijkstra(s);int ans=0;for(int i=1;i<=n;i++)ans=max(ans,d[i]);int ss=team[1];for(int i=1;i<=k;i++)maze[ss][team[i]]=maze[team[i]][ss]=0; Dijkstra(ss);int anss=0;for(int i=1;i<=n;i++)anss=max(anss,d[i]);if(ans<=anss*c)printf("%d\n",ans);else if(ans>anss*c)printf("%d\n",anss);} return 0; }初始化時(shí)將K個(gè)點(diǎn)都扔進(jìn)優(yōu)先隊(duì)列中:
#include<iostream> #include<string> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<cstdio> #include<queue> using namespace std; typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e3+100;int n,m,s,k,c;int team[N];int maze[N][N];struct Node {int id,dis;Node(int ID,int DIS){id=ID;dis=DIS;}bool operator<(const Node &a)const{return dis>a.dis;} };priority_queue<Node>q;int d[N];bool vis[N];void Dijkstra() {while(!q.empty()){Node temp=q.top();q.pop();int u=temp.id;int w=temp.dis;if(vis[u])continue;vis[u]=true;for(int i=1;i<=n;i++){if(d[i]>d[u]+maze[u][i]){d[i]=d[u]+maze[u][i];q.push(Node(i,d[i]));}}} } void init() {while(!q.empty())q.pop();for(int i=1;i<=n;i++){d[i]=inf;vis[i]=false;} }int main() {int w;cin>>w;while(w--){scanf("%d%d%d%d%d",&n,&m,&s,&k,&c);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)maze[i][j]=i==j?0:inf;for(int i=1;i<=k;i++)scanf("%d",team+i);while(m--){int u,v,w;scanf("%d%d%d",&u,&v,&w);if(maze[u][v]>w)maze[u][v]=maze[v][u]=w;}init();d[s]=0;q.push(Node(s,0));Dijkstra();int ans=0;for(int i=1;i<=n;i++)ans=max(ans,d[i]);init();for(int i=1;i<=k;i++){d[team[i]]=0;q.push(Node(team[i],0));}Dijkstra();int anss=0;for(int i=1;i<=n;i++)anss=max(anss,d[i]);if(ans<=anss*c)printf("%d\n",ans);else if(ans>anss*c)printf("%d\n",anss);} return 0; }?
總結(jié)
以上是生活随笔為你收集整理的2019ICPC(南昌) - Fire-Fighting Hero(最短路+思维)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2019ICPC(南昌) - The N
- 下一篇: 2019ICPC(南昌) - Magic