您的位置:首页 > 其它

【图论】[luoguP3905]道路重建

2017-09-14 07:14 211 查看
题目

一个变形的最短路问题 我们可以在每次寻找最短路的时候都去维护一个当前的最小花费 当我们知道当前找的这条边不是被摧毁的边的时候 我们则需要在pay[edge[i].to]和pay[u]中找一个较小的而不用再考虑这条边的长度

用的刚学的堆优化dijkstra

代码如下

#include<iostream>
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<string>

using namespace std;
#define in = read()
typedef long long ll;
const ll size = 500000 + 10000;
const ll size2 = 1000 + 10;

struct point{   ll next,to,dis;}edge[size];
priority_queue <pair<ll , ll> , vector<pair<ll , ll> > , greater<pair<ll , ll> > > q;

ll n,m,d,Beginn,Endd;
ll site;
ll head[size],dis[size],pay[size];
bool exist[size],need[size2][size2];

inline ll read(){
ll num = 0 , f = 1;   char ch = getchar();

while(!isdigit(ch)){
if(ch == '-')   f = -1;
ch = getchar();
}

while(isdigit(ch)){
num = num*10 + ch - '0';
ch = getchar();
}

return num*f;
}

inline void add(ll x, ll y, ll z){
edge[++site].next = head[x];
edge[site].to = y;
edge[site].dis = z;
head[x] = site;
}

int main(){
n in;   m in;
for(int i=1;i<=m;i++){
ll x,y,z;   x in;   y in;   z in;
add(x,y,z);   add(y,x,z);
}
d in;
for(int i=1;i<=d;i++){
ll x,y;   x in;   y in;
need[x][y] = need[y][x] = true;
}
Beginn in;   Endd in;
memset(dis,127/3,sizeof(dis));    dis[Beginn] = 0;
memset(pay,127/3,sizeof(pay));    pay[Beginn] = 0;

pair<ll , ll> x;
q.push(make_pair(0,Beginn));
while(!q.empty()){
x = q.top();    q.pop();    ll u = x.second;
if(exist[u])    continue;
exist[u] = true;
for(int i=head[u];i!=0;i=edge[i].next)
if(edge[i].dis + dis[u] < dis[edge[i].to]){
dis[edge[i].to] = edge[i].dis + dis[u];
if(need[u][edge[i].to])
pay[edge[i].to] = min(pay[edge[i].to],edge[i].dis + pay[u]);
else
pay[edge[i].to] = min(pay[edge[i].to],pay[u]);
q.push(make_pair(dis[edge[i].to],edge[i].to));
}
exist[u] = false;
}

printf("%d",pay[Endd]);
}

//COYG
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: