首页 > 代码库 > poj3662
poj3662
题目大意:有n个节点p条无向边,现在可以选择其中的任意K条免费,如果必须的边多与K跳,则花费多余所需边中权值最大的一个,求最小花费多少。
分析:最短路+二分
我们可以二分答案mid,对于每一个mid求最短路,将最短路中大权值大于mid的边作为免费的集合,否则作为不免费的集合,验证免费集合大小是否大于K
这里有个技巧,就是在求最短路的过程中,把大于mid的边权值变为1,小于的为0那么最后求到的d[e](e为终点)就是需要统计的集合大小
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <set> 5 #include <algorithm> 6 #include <map> 7 #include <queue> 8 #include<vector> 9 #define maxn 101010 #define maxm 100001011 #define INF 0x3fffffff12 using namespace std;13 struct edge {14 int to,w;15 edge(){}16 edge(int _to,int _w){17 to=_to;w=_w;18 }19 };20 typedef pair<int,int> P;21 int V;22 vector<edge> G[maxn];23 int d[maxn];24 int K;25 int dijkstra(int s,int x){26 priority_queue<P,vector<P>,greater<P> >q;27 for(int i=0;i<V;++i)d[i]=INF;28 d[s]=0;29 q.push(P(d[s],s));30 while(!q.empty()){31 P p = q.top();32 q.pop();33 int v = p.second;34 if(d[v]<p.first)continue;35 for(int i=0;i<G[v].size();++i){36 edge e = G[v][i];37 int dd = d[v]+(e.w>=x?1:0);38 if(d[e.to]>dd){39 d[e.to]=dd;40 q.push(P(d[e.to],e.to));41 }42 }43 }44 return d[V-1];45 }46 void solve(){47 int l =0,r = maxm+10;48 while(r-l>1){49 int mid = (l+r)/2;50 if(dijkstra(0,mid)>K)l=mid;51 else r=mid;52 }53 int ans = l;54 if(l>maxm)ans=-1;55 printf("%d\n",ans);56 }57 int main (){58 int n,m;59 while(scanf("%d%d%d",&n,&m,&K)!=EOF){60 for(int i=0;i<=n;++i)G[i].clear();61 V=n;62 int u,v,w;63 for(int i=0;i<m;++i){64 scanf("%d%d%d",&u,&v,&w);65 G[u-1].push_back(edge(v-1,w));66 G[v-1].push_back(edge(u-1,w));67 }68 solve();69 }70 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。