题目链接:点我~~
题意:在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 (转载时请注明本文出处及文章链接)


发表评论
快来吐槽一下吧!