bzoj1614[Usaco2007 Jan]Telephone Lines架设电话线*
bzoj1614[Usaco2007 Jan]Telephone Lines架设电话线
题意:
n个节点,1号节点已经连入互联网,现在需要将整个图连入网络。有K条边可以免费连接,最后总费用为所有连边费用的最大值,求最小总费用。n≤10000
题解:
二分费用,将连边费用大于二分值的长度记为1,否则记为0,求最短路,如果到某个点的距离超过k,则需要增加答案,继续二分。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #define inc(i,j,k) for(int i=j;i<=k;i++) 6 #define maxn 1001 7 #define INF 0x3fffffff 8 using namespace std; 9 10 inline int read(){ 11 char ch=getchar(); int f=1,x=0; 12 while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} 13 while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); 14 return f*x; 15 } 16 struct e{int t,w,y,n;}; e es[maxn*20]; int ess,g[maxn]; 17 void pe(int f,int t,int w){ 18 es[++ess]=(e){t,0,w,g[f]}; g[f]=ess; es[++ess]=(e){f,0,w,g[t]}; g[t]=ess; 19 } 20 bool inq[maxn]; int d[maxn],n,m,k,ans; queue<int>q; 21 bool spfa(){ 22 while(!q.empty())q.pop(); memset(inq,0,sizeof(inq)); inc(i,1,n)d[i]=INF; 23 inq[1]=1; q.push(1); d[1]=0; 24 while(!q.empty()){ 25 int x=q.front(); q.pop(); inq[x]=0; 26 for(int i=g[x];i;i=es[i].n)if(d[es[i].t]>d[x]+es[i].w){ 27 d[es[i].t]=d[x]+es[i].w; if(!inq[es[i].t])inq[es[i].t]=1,q.push(es[i].t); 28 } 29 } 30 if(d[n]>k)return 0;else return 1; 31 } 32 bool check(int x){ 33 inc(i,1,ess)if(es[i].y<=x)es[i].w=0;else es[i].w=1; 34 return spfa(); 35 } 36 int main(){ 37 n=read(); m=read(); k=read(); int l=0,r=0; ans=-1; 38 inc(i,1,m){int a=read(),b=read(),c=read(); pe(a,b,c); r=max(r,c);} 39 while(l<=r){ 40 int mid=(l+r)>>1; if(check(mid))ans=mid,r=mid-1;else l=mid+1; 41 } 42 printf("%d",ans); return 0; 43 }
20160811