题目链接:点我~~
题意:在N个点,M条带权边的图上,查询从点S到点E的最短路径,并且有一次机会可以把一条边的权值变成原来的二分之一。
思路:利用分层图的思想建图,
u->v需要建立,addedge(u+n,v+n),addedge(u,v+n,w/2),表示分两层,当从上层到下层,即使用了题中所给的条件。
#include <bits/stdc++.h> using namespace std; typedef vector<int> VI; typedef long long LL; typedef pair<int,int> PII; typedef pair<double,double> PDD; const int mod=1e9+7; const double eps=1e-8; const int inf=0x3f3f3f3f; const double pi=acos(-1.0); const int MAXN=200010; const LL INF=1e18+10; struct Edge { int v; int cost; Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {} }; vector<Edge>E[MAXN]; void addedge(int u,int v,int w) { E[u].push_back(Edge(v,w)); } bool vis[MAXN]; int cnt[MAXN]; LL dist[MAXN]; bool SPFA(int start,int n) { memset(vis,false,sizeof(vis)); for(int i=1; i<=n; i++)dist[i]=INF; vis[start]=true; dist[start]=0; queue<int>que; while(!que.empty())que.pop(); que.push(start); memset(cnt,0,sizeof(cnt)); cnt[start]=1; while(!que.empty()) { int u=que.front(); que.pop(); vis[u]=false; for(int i=0; i<E[u].size(); i++) { int v=E[u][i].v; if(dist[v]>dist[u]+E[u][i].cost) { dist[v]=dist[u]+E[u][i].cost; if(!vis[v]) { vis[v]=true; que.push(v); } } } } return true; } map<string,int >mp; int main() { int n,m; while(~scanf("%d%d",&n,&m)) { string a,b; int cnt=1; mp.clear(); for(int i=0; i<=n*2; ++i) E[i].clear(); int val=0; for(int i=0; i<m; ++i) { cin>>a>>b>>val; if(!mp[a]) mp[a]=cnt++; if(!mp[b]) mp[b]=cnt++; addedge(mp[a],mp[b],val); addedge(mp[a]+n,mp[b]+n,val); addedge(mp[a],mp[b]+n,val/2); } cin>>a>>b; if(!mp[a]) mp[a]=cnt++; if(!mp[b]) mp[b]=cnt++; SPFA(mp[a],n*2); LL ans=min(dist[mp[b]],dist[mp[b]+n]); if(ans==INF) puts("-1"); else cout<<ans<<endl; } return 0; }
- 版权声明:本文基于《知识共享署名-相同方式共享 3.0 中国大陆许可协议》发布,转载请遵循本协议
- 文章链接:http://www.carlstedt.cn/archives/1145 (转载时请注明本文出处及文章链接)
发表评论
快来吐槽一下吧!