Telephone Lines USACO 月赛

以前做过这套题目

这个题又重新写了:http://www.cnblogs.com/jh818012/archive/2013/05/05/3182681.html

还是以前的思路

一直错在一个地方:决策的时候,如果没有走过,直接更新,如果走过,总是选最小值。如果走的是小于mid值的边,那么用tmp = max(dp[x][u] , e[i].val) 更新。

代码比以前好多了好像、

#define maxn 1005

int dp[maxn][maxn];
int n,m,k;
struct node
{
  int v,next;
  int val;
  int f;
};
node e[10005 * 2 ];
int head[maxn];
int cnt ;
void init()
{
  cnt = 0 ;
  memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
  e[cnt].v = v ;
  e[cnt].val = w;
  e[cnt].next = head[u] ;
  head[u] = cnt ++ ;

  e[cnt].v = u ;
  e[cnt].val = w ;
  e[cnt].next = head[v];
  head[v] = cnt ++ ;
  return ;
}
bool vis[maxn];

void dfs(int u)
{
  vis[u]= 1 ;
  for(int i =  head[u]; i != -1 ; i = e[i].next )
    if(!vis[e[i].v] )
      dfs(e[i].v);
}

queue< pair<int,int> > q;
#define pii pair<int,int>
bool vs[maxn][maxn];

void spfa()
{
  pii cur,tt;
  int u , x;
  while(!q.empty()) q.pop();
  dp[1][0] = 0 ;
  vs[1][0] = 1;
  q.push(make_pair(1,0));
  while(!q.empty())
  {
    cur = q.front();
    q.pop();
    u = cur.first;
    x = cur.second;
    for(int i = head[u]; i != -1 ; i = e[i].next )
    {
      if(e[i].f == 1 )
      {
        tt = make_pair(e[i].v , x + 1 );
        if(x + 1 > k ) continue;
        // printf("%d %d %d %d
",u,x,e[i].v,x+1);
        //int tmp = max(dp[e[i].v][x+1],dp[u][x]);
        if((dp[e[i].v][x+1] == -1 && dp[u][x] >= 0  )|| ( dp[e[i].v][x+1] != -1 && dp[u][x] >= 0 && dp[u][x] < dp[e[i].v][x+1] ) )
        {
          dp[e[i].v][x+1] = dp[u][x] ;
          if(!vs[tt.first][tt.second])
          {
            vs[tt.first][tt.second] = 1 ;
            q.push(tt);
          }
        }
      }
      else if(e[i].f == 0 )
      {
        tt = make_pair(e[i].v,x);
        if(x > k ) continue;
        // printf("%d %d %d %d
",u,x,e[i].v,x);
        int tmp = max(e[i].val , dp[u][x] );
        if(dp[e[i].v][x] == -1 || tmp < dp[e[i].v][x])
        {
          dp[e[i].v][x] = tmp;
          if(!vs[tt.first][tt.second])
          {
            vs[tt.first][tt.second] = 1 ;
            q.push(tt);
          }
        }
      }
    }
    vs[u][x] = 0;
  }
  //if(dp[n][k] >= 0 ) puts("asjklsajk");
}
int check()
{
  memset(dp,-1,sizeof(dp));
  memset(vs,0,sizeof(vs));
  spfa();
  //printf("dp[n][k] = %d
",dp[n][k]);
  return dp[n][k];
}
void build(int x)
{
  for(int i = 1; i <= n ; i ++ )
  {
    for(int j = head[i] ; j != -1 ; j = e[j].next)
      if(e[j].val > x )
        e[j].f = 1;
      else e[j].f = 0 ;
  }
}
int _max;
int main()
{
  int u,v,w;
  while(scanf("%d%d%d",&n,&m,&k)!=EOF)
  {
    init();
    _max = 0 ;
    for(int i = 1 ; i <= m ; i ++ )
    {
      scanf("%d%d%d",&u,&v,&w);
      _max = max(_max , w);
      add(u,v,w);
    }
    dfs(1);
    if(!vis[n])
    {
      printf("-1
");
      continue;
    }
    int left , right ,mid ;
    left = 1 ;
    right = _max ;
    int ans ;
    int res;
    ans = 0x3f3f3f3f;
    while(left < right)
    {
      mid = (left + right ) / 2  ;
      //printf("mid = %d
",mid);
      build(mid);
      res = check();
      //printf("res = %d
",res);
      if(res == -1 )
      {
        // printf("%d
",left);
        left = mid + 1 ;
      }
      else
      {
        ans = min(ans , res);
        right = mid ;
      }
    }
    printf("%d
",ans);
  }
  return 0;
}

/*
8 10 2
1 2 1
1 3 10
2 3 2
3 4 11
3 5 3
4 5 10
4 8 12
4 6 9
5 7 4
6 7 5
*/
View Code
原文地址:https://www.cnblogs.com/jh818012/p/3289282.html