poj3662 Telephone Lines(二分)(spfa)
阿新 • • 發佈:2018-11-11
題目
題解
二分+spfa判斷
一個問題如果滿足二分性,整個問題就變得完全不一樣了!
顯然,花的錢數滿足二分性,問題就變成了判斷是否存在一種免費方案,使得最大邊權小於等於mid;或者說的直白一點,有沒有一條路徑,其上的邊權大於mid的邊的條數小於等於mid。
這下,對於每個mid的,我們使所有原邊權大於mid的現在為1,小於等於mid的現在為0,跑最短路,如果d[ed]<=mid則可行。
程式碼
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int inf=1061109567; const int maxn=1010,maxm=10010; int n,p,k; struct E{int x,y,c,next;}e[maxm*2];int len=0,last[maxn]; void ins(int x,int y,int c) { e[++len]=(E){x,y,c,last[x]};last[x]=len; } int d[maxn]; int q[maxn];int head,tail;bool v[maxn]; void spfa(int mid) { memset(d,63,sizeof(d));d[1]=0; memset(v,false,sizeof(v));v[1]=true; head=0;tail=1; q[0]=1; while(head!=tail) { int x=q[head++];if(head==1000) head=0; v[x]=false; for(int k=last[x];k;k=e[k].next) { int y=e[k].y; if(d[y]>d[x]+(e[k].c>mid)) { d[y]=d[x]+(e[k].c>mid); if(!v[y]) { q[tail++]=y;if(tail==1000) tail=0;//debug ++tail v[y]=true; } } } } } bool check(int mid)//判斷有沒有一條路徑 費用大於mid的邊的邊數 小於等於k { spfa(mid); if(d[n]==inf){puts("-1");exit(0);}//沒有一條路徑可以到達n return d[n]<=k; } int main() { scanf("%d%d%d",&n,&p,&k); for(int i=1;i<=p;i++) { int x,y,c; scanf("%d%d%d",&x,&y,&c); ins(x,y,c);ins(y,x,c); } int l=0,r=1000000,ans; while(l<=r) { int mid=l+r>>1; if(check(mid)) { ans=mid; r=mid-1; } else l=mid+1; } printf("%d\n",ans); return 0; }