寒假复习图论的时候做的,因为把它加在了暑假集训的专题训练里,所以补一下解题报告。
题目链接:http://poj.org/problem?id=3662
题目大意:要在N个点建电话线,目前有K根是免费的,问付费建的电话线中最长的一根至少要多长,才能使点1到点n是联通的。
算法:
二分求最长边的长度。
每次二分要用dijkstra判断合法性,
判断时,一条边如果长度小于等于当前限制的这个长度,那么长度为0,否则,长度就是1
然后dijkstra一下判断是不是N点的距离值小于等于K。
PS:
看了一下这题的AC日期是2013-01-30,居然转眼间半年过去了。
那个时候,二分是递归的,离散化是手写的,if后面单语句是不加大括号的,缩进是诡异的,加双向边是手动写两遍的。
哎。。。真是青涩又DT啊。。。。。
代码如下:
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #define INF 0x3f3f3f3f using namespace std; int E,hash[11000],maxn,head[1100],d[1100],vis[1100]; struct { int u,v,w,nxt; } edge[210000]; void addedge(int u,int v,int w) { edge[E].u=u; edge[E].v=v; edge[E].w=w; edge[E].nxt=head[u]; head[u]=E++; edge[E].u=v; edge[E].v=u; edge[E].w=w; edge[E].nxt=head[v]; head[v]=E++; } struct cmp { bool operator () (pair<int,int>& a, pair<int,int>& b) { return a.second>b.second; } }; bool dlijkstra(int S,int T,int k,int lim) { int u; memset(d,-1,sizeof(d)); memset(vis,0,sizeof(vis)); priority_queue<pair<int,int>,vector<pair<int,int> >,cmp>mm; pair<int,int>node; node.first=S; node.second=0; d[S]=0; mm.push(node); while(!mm.empty()) { u=(mm.top()).first; mm.pop(); if(vis[u])continue; vis[u]=1; if(d[T]!=-1&&d[T]<=k) { return 1; } if(d[u]>k) { return 0; } for(int i=head[u]; i!=-1; i=edge[i].nxt) { int v=edge[i].v; if(edge[i].w<=lim) { if(d[v]==-1||d[v]>d[u]) { d[v]=d[u]; node.first=v; node.second=d[v]; mm.push(node); } } else { if(d[v]==-1||d[v]>d[u]+1) { d[v]=d[u]+1; node.first=v; node.second=d[v]; mm.push(node); } } } } if(d[T]==-1||d[T]>k)return 0; else return 1; } int bfind(int S,int T,int k,int l,int r) { if(l==r)return l; int mid=(l+r)>>1; if(dlijkstra(S,T,k,hash[mid])) return bfind(S,T,k,l,mid); return bfind(S,T,k,mid+1,r); } int main() { int n,p,k,u,v,w,ans,maxn; while(~scanf("%d%d%d",&n,&p,&k)) { memset(head,-1,sizeof(head)); for(int i=1; i<=p; i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); hash[i]=w; } sort(hash+1,hash+p+1); hash[0]=0; int j; for(maxn=1,j=1; j<=p; j++) if(hash[j]!=hash[maxn-1])hash[maxn++]=hash[j]; hash[maxn]=hash[maxn-1]+1; ans=bfind(1,n,k,0,maxn); if(ans==maxn)puts("-1"); else printf("%d\n",hash[ans]); } return 0; }