pku Telephone Lines 二分+最短路

pku Telephone Lines 二分+最短路

题意:
一个无向带权图,要求将第1个节点与第n个节点联通,求路径中第p+1长边。如果p>n,输出0;如果不可能联通,输出-1

解法:
我的做法很搓。。二分+dij最短路,邻接矩阵实现。复杂度高达10^7。。如果哪位神牛有更好的方法,请留言或者E-mail告诉我,谢谢
具体做法如下:二分第p+1边长度len,然后将图的权值重置:如果g[i][j]<=len,则g[i][j]=0,否则g[i][j]=1。然后用dji求最短路。。如果1到n距离小于等于p,则返回true。

代码:
 1  # include  < cstdio >
 2  # include  < vector >
 3  # include  < algorithm >
 4  # include  < queue >
 5  # include  < cstring >
 6  using   namespace  std;
 7  int  n,p,k;
 8  vector < int > len;
 9  int  g[ 1001 ][ 1001 ];
10  int  used[ 1001 ];
11  bool  visited[ 1001 ];
12  void  dfs( int  pos)
13  {
14       if (used[pos])  return ;
15      used[pos] = true ;
16       for ( int  i = 1 ;i <= n;i ++ )
17           if (g[pos][i] !=- 1 )
18              dfs(i);
19  }
20  bool  chk( int  l)
21  {
22      memset(used, - 1 , sizeof (used));
23      memset(visited, 0 , sizeof (visited));
24      used[ 1 ] = 0 ;
25       while ( true )
26      {
27           int  pos =- 1 ,minnum = 0xfffffff ;
28           for ( int  i = 1 ;i <= n;i ++ )
29               if ( ! visited[i] && used[i] !=- 1 && used[i] < minnum)
30                  minnum = used[i],pos = i;
31           if (pos ==- 1 break ;
32          visited[pos] = 1 ;
33           for ( int  i = 1 ;i <= n;i ++ )
34               if ( ! visited[i] && g[pos][i] !=- 1 && (used[i] ==- 1 || used[pos] + (g[pos][i] > l) < used[i]))
35                  used[i] = used[pos] + (g[pos][i] > l);
36      }
37       return  used[n] <= k;
38  }
39  int  main() {
40      scanf( " %d%d%d " , & n, & p, & k);
41      memset(g, - 1 , sizeof (g));
42       while (p -- )
43      {
44           int  a,b,value;
45          scanf( " %d%d%d " , & a, & b, & value);
46           if (g[a][b] ==- 1 || g[a][b] > value)
47              g[a][b] = g[b][a] = value;
48          len.push_back(value);
49      }
50      sort(len.begin(),len.end());
51      memset(used, 0 , sizeof (used));
52      dfs( 1 );
53       if ( ! used[n]) printf( " -1\n " );
54       else
55      {
56           int  s = 0 ,e = len.size() - 1 ;
57           while (s <= e)
58          {
59               int  mid = (s + e) >> 1 ;
60               if (chk(len[mid])) e = mid - 1 ;
61               else  s = mid + 1 ;
62          }
63           if (e ==- 1 ) printf( " 0\n " );
64           else  printf( " %d\n " ,len[e + 1 ]);
65      }
66       return   0 ;
67  }
68 



你可能感兴趣的:(pku Telephone Lines 二分+最短路)