洛谷P1951 收费站_NOI导刊2009提高(2)
题目描述
在某个遥远的国家里,有n个城市。编号为1,2,3,…,n。
这个国家的政府修建了m条双向的公路。每条公路连接着两个城市。沿着某条公路,开车从一个城市到另一个城市,需要花费一定的汽油。
开车每经过一个城市,都会被收取一定的费用(包括起点和终点城市)。所有的收费站都在城市中,在城市间的公路上没有任何的收费站。
小红现在要开车从城市u到城市v(1<=u,v<=n)。她的车最多可以装下s升的汽油。在出发的时候,车的油箱是满的,并且她在路上不想加油。
在路上,每经过一个城市,她都要交一定的费用。如果某次交的费用比较多,她的心情就会变得很糟。所以她想知道,在她能到达目的地的前提下,她交的费用中最多的一次最少是多少。这个问题对于她来说太难了,于是她找到了聪明的你,你能帮帮她吗?
输入输出格式
输入格式:
第一行5个正整数,n,m,u,v,s,分别表示有n个城市,m条公路,从城市u到城市v,车的油箱的容量为s升。
接下来的有n行,每行1个整数,fi表示经过城市i,需要交费fi元。
再接下来有m行,每行3个正整数,ai,bi,ci(1<=ai,bi<=n),表示城市ai和城市bi之间有一条公路,如果从城市ai到城市bi,或者从城市bi到城市ai,需要ci升的汽油。
输出格式:
仅一个整数,表示小红交费最多的一次的最小值。
如果她无法到达城市v,输出-1.
输入输出样例
输入样例#1:
4 4 2 3 8 8 5 6 10 2 1 2 2 4 1 1 3 4 3 4 3
输出样例#1:
8
说明
【数据规模】
对于60%的数据,满足n<=200,m<=10000,s<=200
对于100%的数据,满足n<=10000,m<=50000,s<=1000000000
对于100%的数据,满足ci<=1000000000,fi<=1000000000,可能有两条边连接着相同的城市。
#include<iostream> #include<cstdio> #include<cstring> #define maxn 10010 using namespace std; int n,m,s,t,g,w[maxn],num,head[maxn],mid; bool vis[maxn],ok; struct node{ int to,pre,v; }e[100010]; void Insert(int from,int to,int v){ e[++num].to=to; e[num].v=v; e[num].pre=head[from]; head[from]=num; } void dfs(int now,int gg){ if(now==t){ ok=1; return; } if(ok)return; for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(!vis[to]&&w[to]<=mid&&(gg-e[i].v>=0))dfs(to,gg-e[i].v); } } bool check(){ memset(vis,0,sizeof(vis));ok=0; vis[s]=1; dfs(s,g); if(ok)return 1; return 0; } int main(){ int x,y,z; scanf("%d%d%d%d%d",&n,&m,&s,&t,&g); int l=0x7fffffff,r=0; for(int i=1;i<=n;i++){ scanf("%d",&w[i]); r=max(r,w[i]); } l=w[s]; for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); Insert(x,y,z);Insert(y,x,z); } int ans=-1; while(l<=r){ mid=(l+r)>>1; if(check())ans=mid,r=mid-1; else l=mid+1; } printf("%d",ans); }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define maxn 10010 using namespace std; int n,m,s,t,g,num,head[maxn],w[maxn],f[maxn],mid,dis[maxn]; bool vis[maxn]; struct node{ int to,pre,v; }e[100010]; void Insert(int from,int to,int v){ e[++num].to=to; e[num].v=v; e[num].pre=head[from]; head[from]=num; } struct Node{ int id,dist; bool operator < (const Node b)const{ return dist>b.dist; } }; Node make_node(int x,int y){ Node res; res.id=x;res.dist=y; return res; } bool Dij(int limit){ memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); priority_queue<Node>q; q.push(make_node(s,0)); dis[s]=0; while(!q.empty()){ Node cur=q.top();q.pop();int now=cur.id; if(w[now]>limit)continue; if(vis[now])continue; vis[now]=1; for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(w[to]>limit)continue; if(dis[to]>dis[now]+e[i].v){ dis[to]=dis[now]+e[i].v; q.push(make_node(to,dis[to])); } } } return dis[t]<=g; } int main(){ freopen("Cola.txt","r",stdin); scanf("%d%d%d%d%d",&n,&m,&s,&t,&g); for(int i=1;i<=n;i++){ scanf("%d",&w[i]); f[i]=w[i]; } sort(f+1,f+n+1); int x,y,z; for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); Insert(x,y,z);Insert(y,x,z); } int l=1,r=n,ans=-1; while(l<=r){ mid=(l+r)>>1; if(Dij(f[mid]))ans=f[mid],r=mid-1; else l=mid+1; } printf("%d",ans); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<deque> #define maxn 10010 using namespace std; int n,m,s,t,g,num,head[maxn],dis[maxn],w[maxn],f[maxn]; bool vis[maxn]; struct node{ int to,pre,v; }e[100010]; void Insert(int from,int to,int v){ e[++num].to=to; e[num].v=v; e[num].pre=head[from]; head[from]=num; } bool spfa(int limit){ memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); deque<int>q; q.push_back(s); dis[s]=0;vis[s]=1; while(!q.empty()){ int now=q.front();q.pop_front();vis[now]=0; if(w[now]>limit)continue; for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(w[to]>limit)continue; if(dis[to]>dis[now]+e[i].v){ dis[to]=dis[now]+e[i].v; if(!vis[to]){ vis[to]=1; if(!q.empty()&&dis[to]<dis[q.front()])q.push_front(to); else q.push_back(to); } } } } return dis[t]<=g; } int main(){ scanf("%d%d%d%d%d",&n,&m,&s,&t,&g); for(int i=1;i<=n;i++){ scanf("%d",&w[i]); f[i]=w[i]; } sort(f+1,f+n+1); int x,y,z; for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); Insert(x,y,z);Insert(y,x,z); } int l=1,r=n,ans=-1; while(l<=r){ int mid=(l+r)>>1; if(spfa(f[mid]))ans=f[mid],r=mid-1; else l=mid+1; } printf("%d",ans); }