bzoj:1614 [Usaco2007 Jan]Telephone Lines架設電話線 (luogu 1948)
阿新 • • 發佈:2018-12-11
演算法:(最短路+二分答案)/(分層圖)(Dr_J)/(DP)
難度:NOIP-
為什麼我的第一想法是分層圖...(寫完spfa+二分後發現確實有分層圖的解法)
好吧,我們辣i醬spfa,因為題目中隱約有最小值最大的意思,也可以想到二分。
我們來二分答案(廢話..),二分答案後跑spfa檢驗此mid是否滿足即可
醬大於mid的邊就變成1(很不標準),其他的為0,跑一下spfa,判斷dis[n]是否滿足<=k即可
程式碼如下:
#include <cstdio> #include <iostream> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <queue> #include <deque> #define ll long long #define N 200005 using namespace std; struct node { int next; int to; int val; }edg[N<<1]; int head[N<<1]; int vis[N]; int cnt=1; void init() { cnt=1; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edg[cnt].next=head[u]; edg[cnt].to=v; edg[cnt].val=w; head[u]=cnt++; } int dis[N]; int n,p,k; bool spfa(int mid) { memset(dis,0x3f3f3f3f,sizeof(dis)); memset(vis,0,sizeof(vis)); deque<int>Q; Q.push_back(1); dis[1]=0; vis[1]=1; while(!Q.empty()) { int u = Q.front(); Q.pop_front(); for(int i = head[u];i!=-1;i=edg[i].next) { int to=edg[i].to; int d = (edg[i].val>mid);//滿足為1,不滿足為0 if(dis[to]>dis[u]+d) { dis[to]=dis[u]+d; if(!vis[to]) { vis[to]=1; if(!Q.empty()&&dis[to]<dis[Q.front()]) { Q.push_front(to); }else { Q.push_back(to); } } } } vis[u]=0; } return dis[n]<=k; } int main() { scanf("%d%d%d",&n,&p,&k); init(); int r=0; for(int i = 1;i <= p;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); r=max(r,w)/*把“= ”寫成“- ”*/; } int l=0,ans=-1; while(l<=r) { int mid=(l+r)>>1; if(spfa(mid)) { ans=mid;/*把mid寫成r...*/ r=mid-1; }else { l=mid+1; } } printf("%d\n",ans); return 0 ; }