1. 程式人生 > >poj3662Telephone Lines——二分+最短路

poj3662Telephone Lines——二分+最短路

iostream 賦值 超過 sin lines AC can 開始 div

題目:http://poj.org/problem?id=3662

二分答案找出符合條件的最小長度;

假設了每個長度後,以這個為標準對每條邊賦值,0為小於等於,1為大於,然後按這個值來跑最短路,在看看能否使用不超過k根長電線;

註意不能到達要輸出-1!

不知為何l從0開始就A了,從最短的電線開始就是WA,可怖的細節;

總之,0和1這個技巧很美,打破了最短路的常規思路。

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
queue
<int>q; int n,p,k,head[1005],ct,l,r,dis[1005]; bool vis[1005]; struct N{ int to,next,w,c; N(int t=0,int n=0,int w=0):to(t),next(n),w(w) {} }edge[20005]; bool spfa() { memset(vis,0,sizeof vis); memset(dis,3,sizeof dis); while(q.size())q.pop(); q.push(1);vis[1]=1;dis[1]=0; while
(q.size()) { int x=q.front();q.pop(); vis[x]=0; for(int i=head[x];i;i=edge[i].next) { int u=edge[i].to; if(dis[u]>dis[x]+edge[i].c) { dis[u]=dis[x]+edge[i].c; if(!vis[u]) { vis[u]
=1; q.push(u); } } } } return dis[n]<=k; } bool cl(int x) { for(int i=1;i<=ct;i++) { if(edge[i].w<=x)edge[i].c=0; else edge[i].c=1; } return spfa(); } int main() { while(scanf("%d%d%d",&n,&p,&k)==3) { ct=0; memset(head,0,sizeof head); // l=1000005;//!! l=0; r=0; int x,y,z; for(int i=1;i<=p;i++) { scanf("%d%d%d",&x,&y,&z); edge[++ct]=N(y,head[x],z);head[x]=ct; edge[++ct]=N(x,head[y],z);head[y]=ct; r=max(r,z); // l=min(l,z); } // while(l<r) // { // int mid=(l+r)/2; // if(cl(mid))r=mid; // else l=mid+1; // } int ans=-1;//!!! while(l<=r) { int mid=(l+r)/2; if(cl(mid)) { ans=mid; r=mid-1; } else l=mid+1; } printf("%d\n",ans); } return 0; }

poj3662Telephone Lines——二分+最短路