BZOJ 1614 USACO 07Jan. 洛谷1948 电话线
二分+特殊姿势的check:二分最小代价P,把边权小于等于P的边设为0,其他的设为1,跑一遍最短路,判断dis[n]是否大于K
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int maxn=100010; 7 int n,p,k,tot=0,Maxdis=0,last[maxn],dis[maxn]; 8 bool v[maxn]; 9 struct edge{int to,pre,dis;}e[maxn]; 10 struct que{int pos,dis;}; 11 struct rec{int x,y,dis;}a[maxn]; 12 struct cmp{ 13 bool operator() (const que a,const que b){return a.dis>b.dis;} 14 }; 15 priority_queue<que,vector<que>,cmp>q; 16 17 void read(int &k){ 18 k=0; int f=1; char c=getchar(); 19 while (c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 20 while ('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 21 k*=f; 22 } 23 void add(int x,int y,int z){e[++tot].to=y;e[tot].dis=z;e[tot].pre=last[x];last[x]=tot;} 24 void dijkstra(int x){ 25 dis[x]=0; v[x]=1; q.push((que){x,0}); 26 while (!q.empty()){ 27 que t=q.top(); int now=t.pos; q.pop(); 28 for (int i=last[now],to;i;i=e[i].pre) 29 if (dis[to=e[i].to]>dis[now]+e[i].dis){ 30 dis[to]=dis[now]+e[i].dis; 31 if (!v[to]){ 32 v[to]=1; 33 q.push((que){to,dis[to]}); 34 } 35 } 36 v[now]=0; 37 } 38 } 39 bool check(int x){ 40 tot=0; 41 memset(last,0,sizeof(last)); 42 memset(v,0,sizeof(v)); 43 memset(dis,32,sizeof(dis)); 44 for (int i=1;i<=p;i++){ 45 int d=(a[i].dis<=x)?0:1; 46 add(a[i].x,a[i].y,d); add(a[i].y,a[i].x,d); 47 } 48 dijkstra(1); 49 if (dis[n]>k) return 0; 50 else return 1; 51 } 52 int main(){ 53 read(n); read(p); read(k); 54 if (p<k) return puts("0"),0; 55 for (int i=1;i<=p;i++){ 56 read(a[i].x); read(a[i].y); read(a[i].dis); 57 Maxdis=max(a[i].dis,Maxdis); 58 } 59 int l=0,r=Maxdis; 60 while (l<r){ 61 int mid=(l+r)>>1; 62 if (check(mid)) r=mid; 63 else l=mid+1; 64 } 65 if (check(l)) printf("%d\n",l); else printf("-1"); 66 return 0; 67 }